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 "tree-pass.h"
41 #include "tree-pretty-print.h"
43 #include "basic-block.h"
46 #include "plugin-api.h"
47 #include "hard-reg-set.h"
52 #include "ipa-utils.h"
53 #include "tree-ssa-alias.h"
54 #include "internal-fn.h"
55 #include "gimple-fold.h"
56 #include "gimple-expr.h"
58 #include "alloc-pool.h"
59 #include "symbol-summary.h"
61 #include "ipa-inline.h"
62 #include "diagnostic.h"
66 #include "gimple-pretty-print.h"
67 #include "stor-layout.h"
69 #include "data-streamer.h"
70 #include "lto-streamer.h"
71 #include "streamer-hooks.h"
73 /* Return true when TYPE contains an polymorphic type and thus is interesting
74 for devirtualization machinery. */
76 static bool contains_type_p (tree
, HOST_WIDE_INT
, tree
,
77 bool consider_placement_new
= true,
78 bool consider_bases
= true);
81 contains_polymorphic_type_p (const_tree type
)
83 type
= TYPE_MAIN_VARIANT (type
);
85 if (RECORD_OR_UNION_TYPE_P (type
))
88 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
90 for (tree fld
= TYPE_FIELDS (type
); fld
; fld
= DECL_CHAIN (fld
))
91 if (TREE_CODE (fld
) == FIELD_DECL
92 && !DECL_ARTIFICIAL (fld
)
93 && contains_polymorphic_type_p (TREE_TYPE (fld
)))
97 if (TREE_CODE (type
) == ARRAY_TYPE
)
98 return contains_polymorphic_type_p (TREE_TYPE (type
));
102 /* Return true if it seems valid to use placement new to build EXPECTED_TYPE
103 at possition CUR_OFFSET within TYPE.
105 POD can be changed to an instance of a polymorphic type by
106 placement new. Here we play safe and assume that any
107 non-polymorphic type is POD. */
109 possible_placement_new (tree type
, tree expected_type
,
110 HOST_WIDE_INT cur_offset
)
112 return ((TREE_CODE (type
) != RECORD_TYPE
113 || !TYPE_BINFO (type
)
114 || cur_offset
>= POINTER_SIZE
115 || !polymorphic_type_binfo_p (TYPE_BINFO (type
)))
116 && (!TYPE_SIZE (type
)
117 || !tree_fits_shwi_p (TYPE_SIZE (type
))
119 + (expected_type
? tree_to_uhwi (TYPE_SIZE (expected_type
))
121 <= tree_to_uhwi (TYPE_SIZE (type
)))));
124 /* THIS->OUTER_TYPE is a type of memory object where object of OTR_TYPE
125 is contained at THIS->OFFSET. Walk the memory representation of
126 THIS->OUTER_TYPE and find the outermost class type that match
127 OTR_TYPE or contain OTR_TYPE as a base. Update THIS
130 If OTR_TYPE is NULL, just find outermost polymorphic type with
131 virtual table present at possition OFFSET.
133 For example when THIS represents type
139 and we look for type at offset sizeof(int), we end up with B and offset 0.
140 If the same is produced by multiple inheritance, we end up with A and offset
143 If we can not find corresponding class, give up by setting
144 THIS->OUTER_TYPE to OTR_TYPE and THIS->OFFSET to NULL.
145 Return true when lookup was sucesful.
147 When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
148 valid only via alocation of new polymorphic type inside by means
151 When CONSIDER_BASES is false, only look for actual fields, not base types
155 ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type
,
156 bool consider_placement_new
,
159 tree type
= outer_type
;
160 HOST_WIDE_INT cur_offset
= offset
;
161 bool speculative
= false;
162 bool size_unknown
= false;
163 unsigned HOST_WIDE_INT otr_type_size
= POINTER_SIZE
;
165 /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set. */
168 clear_outer_type (otr_type
);
172 /* See if OFFSET points inside OUTER_TYPE. If it does not, we know
173 that the context is either invalid, or the instance type must be
174 derived from OUTER_TYPE.
176 Because the instance type may contain field whose type is of OUTER_TYPE,
177 we can not derive any effective information about it.
179 TODO: In the case we know all derrived types, we can definitely do better
181 else if (TYPE_SIZE (outer_type
)
182 && tree_fits_shwi_p (TYPE_SIZE (outer_type
))
183 && tree_to_shwi (TYPE_SIZE (outer_type
)) >= 0
184 && tree_to_shwi (TYPE_SIZE (outer_type
)) <= offset
)
186 clear_outer_type (otr_type
);
190 /* If derived type is not allowed, we know that the context is invalid.
191 For dynamic types, we really do not have information about
192 size of the memory location. It is possible that completely
193 different type is stored after outer_type. */
194 if (!maybe_derived_type
&& !dynamic
)
196 clear_speculation ();
202 if (otr_type
&& TYPE_SIZE (otr_type
)
203 && tree_fits_shwi_p (TYPE_SIZE (otr_type
)))
204 otr_type_size
= tree_to_uhwi (TYPE_SIZE (otr_type
));
206 if (!type
|| offset
< 0)
207 goto no_useful_type_info
;
209 /* Find the sub-object the constant actually refers to and mark whether it is
210 an artificial one (as opposed to a user-defined one).
212 This loop is performed twice; first time for outer_type and second time
213 for speculative_outer_type. The second run has SPECULATIVE set. */
216 unsigned HOST_WIDE_INT pos
, size
;
219 /* If we do not know size of TYPE, we need to be more conservative
220 about accepting cases where we can not find EXPECTED_TYPE.
221 Generally the types that do matter here are of constant size.
222 Size_unknown case should be very rare. */
224 && tree_fits_shwi_p (TYPE_SIZE (type
))
225 && tree_to_shwi (TYPE_SIZE (type
)) >= 0)
226 size_unknown
= false;
230 /* On a match, just return what we found. */
232 && types_odr_comparable (type
, otr_type
)
233 && types_same_for_odr (type
, otr_type
))
235 && TREE_CODE (type
) == RECORD_TYPE
237 && polymorphic_type_binfo_p (TYPE_BINFO (type
))))
241 /* If we did not match the offset, just give up on speculation. */
243 /* Also check if speculation did not end up being same as
245 || (types_must_be_same_for_odr (speculative_outer_type
,
247 && (maybe_derived_type
248 == speculative_maybe_derived_type
)))
249 clear_speculation ();
254 /* If type is known to be final, do not worry about derived
255 types. Testing it here may help us to avoid speculation. */
256 if (otr_type
&& TREE_CODE (outer_type
) == RECORD_TYPE
257 && (!in_lto_p
|| odr_type_p (outer_type
))
258 && type_known_to_have_no_deriavations_p (outer_type
))
259 maybe_derived_type
= false;
261 /* Type can not contain itself on an non-zero offset. In that case
262 just give up. Still accept the case where size is now known.
263 Either the second copy may appear past the end of type or within
264 the non-POD buffer located inside the variably sized type
267 goto no_useful_type_info
;
268 /* If we determined type precisely or we have no clue on
269 speuclation, we are done. */
270 if (!maybe_derived_type
|| !speculative_outer_type
271 || !speculation_consistent_p (speculative_outer_type
,
273 speculative_maybe_derived_type
,
276 clear_speculation ();
279 /* Otherwise look into speculation now. */
283 type
= speculative_outer_type
;
284 cur_offset
= speculative_offset
;
290 /* Walk fields and find corresponding on at OFFSET. */
291 if (TREE_CODE (type
) == RECORD_TYPE
)
293 for (fld
= TYPE_FIELDS (type
); fld
; fld
= DECL_CHAIN (fld
))
295 if (TREE_CODE (fld
) != FIELD_DECL
)
298 pos
= int_bit_position (fld
);
299 if (pos
> (unsigned HOST_WIDE_INT
)cur_offset
)
302 /* Do not consider vptr itself. Not even for placement new. */
303 if (!pos
&& DECL_ARTIFICIAL (fld
)
304 && POINTER_TYPE_P (TREE_TYPE (fld
))
306 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
309 if (!DECL_SIZE (fld
) || !tree_fits_uhwi_p (DECL_SIZE (fld
)))
310 goto no_useful_type_info
;
311 size
= tree_to_uhwi (DECL_SIZE (fld
));
313 /* We can always skip types smaller than pointer size:
314 those can not contain a virtual table pointer.
316 Disqualifying fields that are too small to fit OTR_TYPE
317 saves work needed to walk them for no benefit.
318 Because of the way the bases are packed into a class, the
319 field's size may be smaller than type size, so it needs
320 to be done with a care. */
322 if (pos
<= (unsigned HOST_WIDE_INT
)cur_offset
323 && (pos
+ size
) >= (unsigned HOST_WIDE_INT
)cur_offset
326 || !TYPE_SIZE (TREE_TYPE (fld
))
327 || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld
)))
328 || (pos
+ tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld
))))
329 >= cur_offset
+ otr_type_size
))
334 goto no_useful_type_info
;
336 type
= TYPE_MAIN_VARIANT (TREE_TYPE (fld
));
338 /* DECL_ARTIFICIAL represents a basetype. */
339 if (!DECL_ARTIFICIAL (fld
))
345 /* As soon as we se an field containing the type,
346 we know we are not looking for derivations. */
347 maybe_derived_type
= false;
351 speculative_outer_type
= type
;
352 speculative_offset
= cur_offset
;
353 speculative_maybe_derived_type
= false;
356 else if (!consider_bases
)
357 goto no_useful_type_info
;
359 else if (TREE_CODE (type
) == ARRAY_TYPE
)
361 tree subtype
= TYPE_MAIN_VARIANT (TREE_TYPE (type
));
363 /* Give up if we don't know array field size.
364 Also give up on non-polymorphic types as they are used
365 as buffers for placement new. */
366 if (!TYPE_SIZE (subtype
)
367 || !tree_fits_shwi_p (TYPE_SIZE (subtype
))
368 || tree_to_shwi (TYPE_SIZE (subtype
)) <= 0
369 || !contains_polymorphic_type_p (subtype
))
370 goto no_useful_type_info
;
372 HOST_WIDE_INT new_offset
= cur_offset
% tree_to_shwi (TYPE_SIZE (subtype
));
374 /* We may see buffer for placement new. In this case the expected type
375 can be bigger than the subtype. */
376 if (TYPE_SIZE (subtype
)
377 && (cur_offset
+ otr_type_size
378 > tree_to_uhwi (TYPE_SIZE (subtype
))))
379 goto no_useful_type_info
;
381 cur_offset
= new_offset
;
387 maybe_derived_type
= false;
391 speculative_outer_type
= type
;
392 speculative_offset
= cur_offset
;
393 speculative_maybe_derived_type
= false;
396 /* Give up on anything else. */
400 if (maybe_derived_type
&& !speculative
401 && TREE_CODE (outer_type
) == RECORD_TYPE
402 && TREE_CODE (otr_type
) == RECORD_TYPE
403 && TYPE_BINFO (otr_type
)
405 && get_binfo_at_offset (TYPE_BINFO (otr_type
), 0, outer_type
))
407 clear_outer_type (otr_type
);
408 if (!speculative_outer_type
409 || !speculation_consistent_p (speculative_outer_type
,
411 speculative_maybe_derived_type
,
413 clear_speculation ();
414 if (speculative_outer_type
)
417 type
= speculative_outer_type
;
418 cur_offset
= speculative_offset
;
423 /* We found no way to embedd EXPECTED_TYPE in TYPE.
424 We still permit two special cases - placement new and
425 the case of variadic types containing themselves. */
427 && consider_placement_new
428 && (size_unknown
|| !type
|| maybe_derived_type
429 || possible_placement_new (type
, otr_type
, cur_offset
)))
431 /* In these weird cases we want to accept the context.
432 In non-speculative run we have no useful outer_type info
433 (TODO: we may eventually want to record upper bound on the
434 type size that can be used to prune the walk),
435 but we still want to consider speculation that may
439 clear_outer_type (otr_type
);
440 if (!speculative_outer_type
441 || !speculation_consistent_p (speculative_outer_type
,
443 speculative_maybe_derived_type
,
445 clear_speculation ();
446 if (speculative_outer_type
)
449 type
= speculative_outer_type
;
450 cur_offset
= speculative_offset
;
456 clear_speculation ();
461 clear_speculation ();
464 clear_outer_type (otr_type
);
472 /* Return true if OUTER_TYPE contains OTR_TYPE at OFFSET.
473 CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can
474 be built within OUTER_TYPE by means of placement new. CONSIDER_BASES makes
475 function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or as
476 base of one of fields of OUTER_TYPE. */
479 contains_type_p (tree outer_type
, HOST_WIDE_INT offset
,
481 bool consider_placement_new
,
484 ipa_polymorphic_call_context context
;
486 /* Check that type is within range. */
489 if (TYPE_SIZE (outer_type
) && TYPE_SIZE (otr_type
)
490 && TREE_CODE (outer_type
) == INTEGER_CST
491 && TREE_CODE (otr_type
) == INTEGER_CST
492 && wi::ltu_p (wi::to_offset (outer_type
), (wi::to_offset (otr_type
) + offset
)))
495 context
.offset
= offset
;
496 context
.outer_type
= TYPE_MAIN_VARIANT (outer_type
);
497 context
.maybe_derived_type
= false;
498 return context
.restrict_to_inner_class (otr_type
, consider_placement_new
, consider_bases
);
502 /* We know that the instance is stored in variable or parameter
503 (not dynamically allocated) and we want to disprove the fact
504 that it may be in construction at invocation of CALL.
506 BASE represents memory location where instance is stored.
507 If BASE is NULL, it is assumed to be global memory.
508 OUTER_TYPE is known type of the instance or NULL if not
511 For the variable to be in construction we actually need to
512 be in constructor of corresponding global variable or
513 the inline stack of CALL must contain the constructor.
514 Check this condition. This check works safely only before
515 IPA passes, because inline stacks may become out of date
519 decl_maybe_in_construction_p (tree base
, tree outer_type
,
520 gimple call
, tree function
)
523 outer_type
= TYPE_MAIN_VARIANT (outer_type
);
524 gcc_assert (!base
|| DECL_P (base
));
526 /* After inlining the code unification optimizations may invalidate
527 inline stacks. Also we need to give up on global variables after
528 IPA, because addresses of these may have been propagated to their
530 if (DECL_STRUCT_FUNCTION (function
)->after_inlining
)
533 /* Pure functions can not do any changes on the dynamic type;
534 that require writting to memory. */
535 if ((!base
|| !auto_var_in_fn_p (base
, function
))
536 && flags_from_decl_or_type (function
) & (ECF_PURE
| ECF_CONST
))
539 for (tree block
= gimple_block (call
); block
&& TREE_CODE (block
) == BLOCK
;
540 block
= BLOCK_SUPERCONTEXT (block
))
541 if (BLOCK_ABSTRACT_ORIGIN (block
)
542 && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block
)) == FUNCTION_DECL
)
544 tree fn
= BLOCK_ABSTRACT_ORIGIN (block
);
546 if (TREE_CODE (TREE_TYPE (fn
)) != METHOD_TYPE
547 || (!DECL_CXX_CONSTRUCTOR_P (fn
)
548 && !DECL_CXX_DESTRUCTOR_P (fn
)))
550 /* Watch for clones where we constant propagated the first
551 argument (pointer to the instance). */
552 fn
= DECL_ABSTRACT_ORIGIN (fn
);
554 || (base
&& !is_global_var (base
))
555 || TREE_CODE (TREE_TYPE (fn
)) != METHOD_TYPE
556 || (!DECL_CXX_CONSTRUCTOR_P (fn
)
557 && !DECL_CXX_DESTRUCTOR_P (fn
)))
560 if (flags_from_decl_or_type (fn
) & (ECF_PURE
| ECF_CONST
))
563 tree type
= TYPE_MAIN_VARIANT (method_class_type (TREE_TYPE (fn
)));
565 if (!outer_type
|| !types_odr_comparable (type
, outer_type
))
567 if (TREE_CODE (type
) == RECORD_TYPE
569 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
572 else if (types_same_for_odr (type
, outer_type
))
576 if (!base
|| (TREE_CODE (base
) == VAR_DECL
&& is_global_var (base
)))
578 if (TREE_CODE (TREE_TYPE (function
)) != METHOD_TYPE
579 || (!DECL_CXX_CONSTRUCTOR_P (function
)
580 && !DECL_CXX_DESTRUCTOR_P (function
)))
582 if (!DECL_ABSTRACT_ORIGIN (function
))
584 /* Watch for clones where we constant propagated the first
585 argument (pointer to the instance). */
586 function
= DECL_ABSTRACT_ORIGIN (function
);
588 || TREE_CODE (TREE_TYPE (function
)) != METHOD_TYPE
589 || (!DECL_CXX_CONSTRUCTOR_P (function
)
590 && !DECL_CXX_DESTRUCTOR_P (function
)))
593 tree type
= TYPE_MAIN_VARIANT (method_class_type (TREE_TYPE (function
)));
594 if (!outer_type
|| !types_odr_comparable (type
, outer_type
))
596 if (TREE_CODE (type
) == RECORD_TYPE
598 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
601 else if (types_same_for_odr (type
, outer_type
))
607 /* Dump human readable context to F. If NEWLINE is true, it will be terminated
611 ipa_polymorphic_call_context::dump (FILE *f
, bool newline
) const
615 fprintf (f
, "Call is known to be undefined");
619 fprintf (f
, "nothing known");
620 if (outer_type
|| offset
)
622 fprintf (f
, "Outer type%s:", dynamic
? " (dynamic)":"");
623 print_generic_expr (f
, outer_type
, TDF_SLIM
);
624 if (maybe_derived_type
)
625 fprintf (f
, " (or a derived type)");
626 if (maybe_in_construction
)
627 fprintf (f
, " (maybe in construction)");
628 fprintf (f
, " offset "HOST_WIDE_INT_PRINT_DEC
,
631 if (speculative_outer_type
)
633 if (outer_type
|| offset
)
635 fprintf (f
, "Speculative outer type:");
636 print_generic_expr (f
, speculative_outer_type
, TDF_SLIM
);
637 if (speculative_maybe_derived_type
)
638 fprintf (f
, " (or a derived type)");
639 fprintf (f
, " at offset "HOST_WIDE_INT_PRINT_DEC
,
647 /* Print context to stderr. */
650 ipa_polymorphic_call_context::debug () const
655 /* Stream out the context to OB. */
658 ipa_polymorphic_call_context::stream_out (struct output_block
*ob
) const
660 struct bitpack_d bp
= bitpack_create (ob
->main_stream
);
662 bp_pack_value (&bp
, invalid
, 1);
663 bp_pack_value (&bp
, maybe_in_construction
, 1);
664 bp_pack_value (&bp
, maybe_derived_type
, 1);
665 bp_pack_value (&bp
, speculative_maybe_derived_type
, 1);
666 bp_pack_value (&bp
, dynamic
, 1);
667 bp_pack_value (&bp
, outer_type
!= NULL
, 1);
668 bp_pack_value (&bp
, offset
!= 0, 1);
669 bp_pack_value (&bp
, speculative_outer_type
!= NULL
, 1);
670 streamer_write_bitpack (&bp
);
672 if (outer_type
!= NULL
)
673 stream_write_tree (ob
, outer_type
, true);
675 streamer_write_hwi (ob
, offset
);
676 if (speculative_outer_type
!= NULL
)
678 stream_write_tree (ob
, speculative_outer_type
, true);
679 streamer_write_hwi (ob
, speculative_offset
);
682 gcc_assert (!speculative_offset
);
685 /* Stream in the context from IB and DATA_IN. */
688 ipa_polymorphic_call_context::stream_in (struct lto_input_block
*ib
,
689 struct data_in
*data_in
)
691 struct bitpack_d bp
= streamer_read_bitpack (ib
);
693 invalid
= bp_unpack_value (&bp
, 1);
694 maybe_in_construction
= bp_unpack_value (&bp
, 1);
695 maybe_derived_type
= bp_unpack_value (&bp
, 1);
696 speculative_maybe_derived_type
= bp_unpack_value (&bp
, 1);
697 dynamic
= bp_unpack_value (&bp
, 1);
698 bool outer_type_p
= bp_unpack_value (&bp
, 1);
699 bool offset_p
= bp_unpack_value (&bp
, 1);
700 bool speculative_outer_type_p
= bp_unpack_value (&bp
, 1);
703 outer_type
= stream_read_tree (ib
, data_in
);
707 offset
= (HOST_WIDE_INT
) streamer_read_hwi (ib
);
710 if (speculative_outer_type_p
)
712 speculative_outer_type
= stream_read_tree (ib
, data_in
);
713 speculative_offset
= (HOST_WIDE_INT
) streamer_read_hwi (ib
);
717 speculative_outer_type
= NULL
;
718 speculative_offset
= 0;
722 /* Proudce polymorphic call context for call method of instance
723 that is located within BASE (that is assumed to be a decl) at offset OFF. */
726 ipa_polymorphic_call_context::set_by_decl (tree base
, HOST_WIDE_INT off
)
728 gcc_assert (DECL_P (base
));
729 clear_speculation ();
731 if (!contains_polymorphic_type_p (TREE_TYPE (base
)))
737 outer_type
= TYPE_MAIN_VARIANT (TREE_TYPE (base
));
739 /* Make very conservative assumption that all objects
740 may be in construction.
742 It is up to caller to revisit this via
743 get_dynamic_type or decl_maybe_in_construction_p. */
744 maybe_in_construction
= true;
745 maybe_derived_type
= false;
749 /* CST is an invariant (address of decl), try to get meaningful
750 polymorphic call context for polymorphic call of method
751 if instance of OTR_TYPE that is located at offset OFF of this invariant.
752 Return FALSE if nothing meaningful can be found. */
755 ipa_polymorphic_call_context::set_by_invariant (tree cst
,
759 HOST_WIDE_INT offset2
, size
, max_size
;
764 clear_outer_type (otr_type
);
766 if (TREE_CODE (cst
) != ADDR_EXPR
)
769 cst
= TREE_OPERAND (cst
, 0);
770 base
= get_ref_base_and_extent (cst
, &offset2
, &size
, &max_size
);
771 if (!DECL_P (base
) || max_size
== -1 || max_size
!= size
)
774 /* Only type inconsistent programs can have otr_type that is
775 not part of outer type. */
776 if (otr_type
&& !contains_type_p (TREE_TYPE (base
), off
, otr_type
))
779 set_by_decl (base
, off
);
783 /* See if OP is SSA name initialized as a copy or by single assignment.
784 If so, walk the SSA graph up. Because simple PHI conditional is considered
785 copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
789 walk_ssa_copies (tree op
, hash_set
<tree
> **global_visited
= NULL
)
791 hash_set
<tree
> *visited
= NULL
;
793 while (TREE_CODE (op
) == SSA_NAME
794 && !SSA_NAME_IS_DEFAULT_DEF (op
)
795 && SSA_NAME_DEF_STMT (op
)
796 && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op
))
797 || gimple_code (SSA_NAME_DEF_STMT (op
)) == GIMPLE_PHI
))
801 if (!*global_visited
)
802 *global_visited
= new hash_set
<tree
>;
803 if ((*global_visited
)->add (op
))
809 visited
= new hash_set
<tree
>;
810 if (visited
->add (op
))
818 This pattern is implicitly produced for casts to non-primary
819 bases. When doing context analysis, we do not really care
820 about the case pointer is NULL, becuase the call will be
822 if (gimple_code (SSA_NAME_DEF_STMT (op
)) == GIMPLE_PHI
)
824 gimple phi
= SSA_NAME_DEF_STMT (op
);
826 if (gimple_phi_num_args (phi
) > 2)
828 if (gimple_phi_num_args (phi
) == 1)
829 op
= gimple_phi_arg_def (phi
, 0);
830 else if (integer_zerop (gimple_phi_arg_def (phi
, 0)))
831 op
= gimple_phi_arg_def (phi
, 1);
832 else if (integer_zerop (gimple_phi_arg_def (phi
, 1)))
833 op
= gimple_phi_arg_def (phi
, 0);
839 if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op
)))
841 op
= gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op
));
851 /* Create polymorphic call context from IP invariant CST.
852 This is typically &global_var.
853 OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF
854 is offset of call. */
856 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst
,
860 clear_speculation ();
861 set_by_invariant (cst
, otr_type
, off
);
864 /* Build context for pointer REF contained in FNDECL at statement STMT.
865 if INSTANCE is non-NULL, return pointer to the object described by
866 the context or DECL where context is contained in. */
868 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl
,
873 tree otr_type
= NULL
;
875 hash_set
<tree
> *visited
= NULL
;
877 if (TREE_CODE (ref
) == OBJ_TYPE_REF
)
879 otr_type
= obj_type_ref_class (ref
);
880 base_pointer
= OBJ_TYPE_REF_OBJECT (ref
);
885 /* Set up basic info in case we find nothing interesting in the analysis. */
886 clear_speculation ();
887 clear_outer_type (otr_type
);
890 /* Walk SSA for outer object. */
893 base_pointer
= walk_ssa_copies (base_pointer
, &visited
);
894 if (TREE_CODE (base_pointer
) == ADDR_EXPR
)
896 HOST_WIDE_INT size
, max_size
;
897 HOST_WIDE_INT offset2
;
898 tree base
= get_ref_base_and_extent (TREE_OPERAND (base_pointer
, 0),
899 &offset2
, &size
, &max_size
);
901 if (max_size
!= -1 && max_size
== size
)
902 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base
)),
905 NULL
/* Do not change outer type. */);
907 /* If this is a varying address, punt. */
908 if ((TREE_CODE (base
) == MEM_REF
|| DECL_P (base
))
912 /* We found dereference of a pointer. Type of the pointer
913 and MEM_REF is meaningless, but we can look futher. */
914 if (TREE_CODE (base
) == MEM_REF
)
916 base_pointer
= TREE_OPERAND (base
, 0);
918 += offset2
+ mem_ref_offset (base
).to_short_addr () * BITS_PER_UNIT
;
921 /* We found base object. In this case the outer_type
923 else if (DECL_P (base
))
927 /* Only type inconsistent programs can have otr_type that is
928 not part of outer type. */
930 && !contains_type_p (TREE_TYPE (base
),
931 offset
+ offset2
, otr_type
))
935 *instance
= base_pointer
;
938 set_by_decl (base
, offset
+ offset2
);
939 if (outer_type
&& maybe_in_construction
&& stmt
)
940 maybe_in_construction
941 = decl_maybe_in_construction_p (base
,
955 else if (TREE_CODE (base_pointer
) == POINTER_PLUS_EXPR
956 && tree_fits_uhwi_p (TREE_OPERAND (base_pointer
, 1)))
958 offset
+= tree_to_shwi (TREE_OPERAND (base_pointer
, 1))
960 base_pointer
= TREE_OPERAND (base_pointer
, 0);
969 /* Try to determine type of the outer object. */
970 if (TREE_CODE (base_pointer
) == SSA_NAME
971 && SSA_NAME_IS_DEFAULT_DEF (base_pointer
)
972 && TREE_CODE (SSA_NAME_VAR (base_pointer
)) == PARM_DECL
)
974 /* See if parameter is THIS pointer of a method. */
975 if (TREE_CODE (TREE_TYPE (fndecl
)) == METHOD_TYPE
976 && SSA_NAME_VAR (base_pointer
) == DECL_ARGUMENTS (fndecl
))
979 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer
)));
980 gcc_assert (TREE_CODE (outer_type
) == RECORD_TYPE
981 || TREE_CODE (outer_type
) == UNION_TYPE
);
983 /* Dynamic casting has possibly upcasted the type
984 in the hiearchy. In this case outer type is less
985 informative than inner type and we should forget
988 && !contains_type_p (outer_type
, offset
,
990 || !contains_polymorphic_type_p (outer_type
))
994 *instance
= base_pointer
;
1000 /* If the function is constructor or destructor, then
1001 the type is possibly in construction, but we know
1002 it is not derived type. */
1003 if (DECL_CXX_CONSTRUCTOR_P (fndecl
)
1004 || DECL_CXX_DESTRUCTOR_P (fndecl
))
1006 maybe_in_construction
= true;
1007 maybe_derived_type
= false;
1011 maybe_derived_type
= true;
1012 maybe_in_construction
= false;
1015 *instance
= base_pointer
;
1018 /* Non-PODs passed by value are really passed by invisible
1019 reference. In this case we also know the type of the
1021 if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer
)))
1024 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer
)));
1025 /* Only type inconsistent programs can have otr_type that is
1026 not part of outer type. */
1027 if (otr_type
&& !contains_type_p (outer_type
, offset
,
1032 *instance
= base_pointer
;
1035 /* Non-polymorphic types have no interest for us. */
1036 else if (!otr_type
&& !contains_polymorphic_type_p (outer_type
))
1040 *instance
= base_pointer
;
1043 maybe_derived_type
= false;
1044 maybe_in_construction
= false;
1046 *instance
= base_pointer
;
1051 tree base_type
= TREE_TYPE (base_pointer
);
1053 if (TREE_CODE (base_pointer
) == SSA_NAME
1054 && SSA_NAME_IS_DEFAULT_DEF (base_pointer
)
1055 && !(TREE_CODE (SSA_NAME_VAR (base_pointer
)) == PARM_DECL
1056 || TREE_CODE (SSA_NAME_VAR (base_pointer
)) == RESULT_DECL
))
1060 *instance
= base_pointer
;
1063 if (TREE_CODE (base_pointer
) == SSA_NAME
1064 && SSA_NAME_DEF_STMT (base_pointer
)
1065 && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer
)))
1066 base_type
= TREE_TYPE (gimple_assign_rhs1
1067 (SSA_NAME_DEF_STMT (base_pointer
)));
1069 if (POINTER_TYPE_P (base_type
))
1070 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base_type
)),
1072 true, NULL
/* Do not change type here */);
1073 /* TODO: There are multiple ways to derive a type. For instance
1074 if BASE_POINTER is passed to an constructor call prior our refernece.
1075 We do not make this type of flow sensitive analysis yet. */
1077 *instance
= base_pointer
;
1081 /* Structure to be passed in between detect_type_change and
1082 check_stmt_for_type_change. */
1084 struct type_change_info
1086 /* Offset into the object where there is the virtual method pointer we are
1088 HOST_WIDE_INT offset
;
1089 /* The declaration or SSA_NAME pointer of the base that we are checking for
1092 /* The reference to virtual table pointer used. */
1095 /* If we actually can tell the type that the object has changed to, it is
1096 stored in this field. Otherwise it remains NULL_TREE. */
1097 tree known_current_type
;
1098 HOST_WIDE_INT known_current_offset
;
1100 /* Set to true if dynamic type change has been detected. */
1101 bool type_maybe_changed
;
1102 /* Set to true if multiple types have been encountered. known_current_type
1103 must be disregarded in that case. */
1104 bool multiple_types_encountered
;
1105 /* Set to true if we possibly missed some dynamic type changes and we should
1106 consider the set to be speculative. */
1108 bool seen_unanalyzed_store
;
1111 /* Return true if STMT is not call and can modify a virtual method table pointer.
1112 We take advantage of fact that vtable stores must appear within constructor
1113 and destructor functions. */
1116 noncall_stmt_may_be_vtbl_ptr_store (gimple stmt
)
1118 if (is_gimple_assign (stmt
))
1120 tree lhs
= gimple_assign_lhs (stmt
);
1122 if (gimple_clobber_p (stmt
))
1124 if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs
)))
1126 if (flag_strict_aliasing
1127 && !POINTER_TYPE_P (TREE_TYPE (lhs
)))
1130 if (TREE_CODE (lhs
) == COMPONENT_REF
1131 && !DECL_VIRTUAL_P (TREE_OPERAND (lhs
, 1)))
1133 /* In the future we might want to use get_base_ref_and_offset to find
1134 if there is a field corresponding to the offset and if so, proceed
1135 almost like if it was a component ref. */
1139 /* Code unification may mess with inline stacks. */
1140 if (cfun
->after_inlining
)
1143 /* Walk the inline stack and watch out for ctors/dtors.
1144 TODO: Maybe we can require the store to appear in toplevel
1145 block of CTOR/DTOR. */
1146 for (tree block
= gimple_block (stmt
); block
&& TREE_CODE (block
) == BLOCK
;
1147 block
= BLOCK_SUPERCONTEXT (block
))
1148 if (BLOCK_ABSTRACT_ORIGIN (block
)
1149 && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block
)) == FUNCTION_DECL
)
1151 tree fn
= BLOCK_ABSTRACT_ORIGIN (block
);
1153 if (flags_from_decl_or_type (fn
) & (ECF_PURE
| ECF_CONST
))
1155 return (TREE_CODE (TREE_TYPE (fn
)) == METHOD_TYPE
1156 && (DECL_CXX_CONSTRUCTOR_P (fn
)
1157 || DECL_CXX_DESTRUCTOR_P (fn
)));
1159 return (TREE_CODE (TREE_TYPE (current_function_decl
)) == METHOD_TYPE
1160 && (DECL_CXX_CONSTRUCTOR_P (current_function_decl
)
1161 || DECL_CXX_DESTRUCTOR_P (current_function_decl
)));
1164 /* If STMT can be proved to be an assignment to the virtual method table
1165 pointer of ANALYZED_OBJ and the type associated with the new table
1166 identified, return the type. Otherwise return NULL_TREE if type changes
1167 in unknown way or ERROR_MARK_NODE if type is unchanged. */
1170 extr_type_from_vtbl_ptr_store (gimple stmt
, struct type_change_info
*tci
,
1171 HOST_WIDE_INT
*type_offset
)
1173 HOST_WIDE_INT offset
, size
, max_size
;
1174 tree lhs
, rhs
, base
;
1176 if (!gimple_assign_single_p (stmt
))
1179 lhs
= gimple_assign_lhs (stmt
);
1180 rhs
= gimple_assign_rhs1 (stmt
);
1181 if (TREE_CODE (lhs
) != COMPONENT_REF
1182 || !DECL_VIRTUAL_P (TREE_OPERAND (lhs
, 1)))
1185 fprintf (dump_file
, " LHS is not virtual table.\n");
1189 if (tci
->vtbl_ptr_ref
&& operand_equal_p (lhs
, tci
->vtbl_ptr_ref
, 0))
1193 base
= get_ref_base_and_extent (lhs
, &offset
, &size
, &max_size
);
1194 if (DECL_P (tci
->instance
))
1196 if (base
!= tci
->instance
)
1200 fprintf (dump_file
, " base:");
1201 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1202 fprintf (dump_file
, " does not match instance:");
1203 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1204 fprintf (dump_file
, "\n");
1209 else if (TREE_CODE (base
) == MEM_REF
)
1211 if (!operand_equal_p (tci
->instance
, TREE_OPERAND (base
, 0), 0))
1215 fprintf (dump_file
, " base mem ref:");
1216 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1217 fprintf (dump_file
, " does not match instance:");
1218 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1219 fprintf (dump_file
, "\n");
1223 if (!integer_zerop (TREE_OPERAND (base
, 1)))
1225 if (!tree_fits_shwi_p (TREE_OPERAND (base
, 1)))
1229 fprintf (dump_file
, " base mem ref:");
1230 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1231 fprintf (dump_file
, " has non-representable offset:");
1232 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1233 fprintf (dump_file
, "\n");
1238 offset
+= tree_to_shwi (TREE_OPERAND (base
, 1)) * BITS_PER_UNIT
;
1241 else if (!operand_equal_p (tci
->instance
, base
, 0)
1246 fprintf (dump_file
, " base:");
1247 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1248 fprintf (dump_file
, " does not match instance:");
1249 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1250 fprintf (dump_file
, " with offset %i\n", (int)tci
->offset
);
1252 return tci
->offset
> POINTER_SIZE
? error_mark_node
: NULL_TREE
;
1254 if (offset
!= tci
->offset
1255 || size
!= POINTER_SIZE
1256 || max_size
!= POINTER_SIZE
)
1259 fprintf (dump_file
, " wrong offset %i!=%i or size %i\n",
1260 (int)offset
, (int)tci
->offset
, (int)size
);
1261 return offset
+ POINTER_SIZE
<= tci
->offset
1263 && tci
->offset
+ POINTER_SIZE
> offset
+ max_size
)
1264 ? error_mark_node
: NULL
;
1269 unsigned HOST_WIDE_INT offset2
;
1271 if (!vtable_pointer_value_to_vtable (rhs
, &vtable
, &offset2
))
1274 fprintf (dump_file
, " Failed to lookup binfo\n");
1278 tree binfo
= subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable
)),
1283 fprintf (dump_file
, " Construction vtable used\n");
1284 /* FIXME: We should suport construction contexts. */
1288 *type_offset
= tree_to_shwi (BINFO_OFFSET (binfo
)) * BITS_PER_UNIT
;
1289 return DECL_CONTEXT (vtable
);
1292 /* Record dynamic type change of TCI to TYPE. */
1295 record_known_type (struct type_change_info
*tci
, tree type
, HOST_WIDE_INT offset
)
1301 fprintf (dump_file
, " Recording type: ");
1302 print_generic_expr (dump_file
, type
, TDF_SLIM
);
1303 fprintf (dump_file
, " at offset %i\n", (int)offset
);
1306 fprintf (dump_file
, " Recording unknown type\n");
1309 /* If we found a constructor of type that is not polymorphic or
1310 that may contain the type in question as a field (not as base),
1311 restrict to the inner class first to make type matching bellow
1315 || (TREE_CODE (type
) != RECORD_TYPE
1316 || !TYPE_BINFO (type
)
1317 || !polymorphic_type_binfo_p (TYPE_BINFO (type
)))))
1319 ipa_polymorphic_call_context context
;
1321 context
.offset
= offset
;
1322 context
.outer_type
= type
;
1323 context
.maybe_in_construction
= false;
1324 context
.maybe_derived_type
= false;
1325 context
.dynamic
= true;
1326 /* If we failed to find the inner type, we know that the call
1327 would be undefined for type produced here. */
1328 if (!context
.restrict_to_inner_class (tci
->otr_type
))
1331 fprintf (dump_file
, " Ignoring; does not contain otr_type\n");
1334 /* Watch for case we reached an POD type and anticipate placement
1336 if (!context
.maybe_derived_type
)
1338 type
= context
.outer_type
;
1339 offset
= context
.offset
;
1342 if (tci
->type_maybe_changed
1343 && (!types_same_for_odr (type
, tci
->known_current_type
)
1344 || offset
!= tci
->known_current_offset
))
1345 tci
->multiple_types_encountered
= true;
1346 tci
->known_current_type
= TYPE_MAIN_VARIANT (type
);
1347 tci
->known_current_offset
= offset
;
1348 tci
->type_maybe_changed
= true;
1351 /* Callback of walk_aliased_vdefs and a helper function for
1352 detect_type_change to check whether a particular statement may modify
1353 the virtual table pointer, and if possible also determine the new type of
1354 the (sub-)object. It stores its result into DATA, which points to a
1355 type_change_info structure. */
1358 check_stmt_for_type_change (ao_ref
*ao ATTRIBUTE_UNUSED
, tree vdef
, void *data
)
1360 gimple stmt
= SSA_NAME_DEF_STMT (vdef
);
1361 struct type_change_info
*tci
= (struct type_change_info
*) data
;
1364 /* If we already gave up, just terminate the rest of walk. */
1365 if (tci
->multiple_types_encountered
)
1368 if (is_gimple_call (stmt
))
1370 if (gimple_call_flags (stmt
) & (ECF_CONST
| ECF_PURE
))
1373 /* Check for a constructor call. */
1374 if ((fn
= gimple_call_fndecl (stmt
)) != NULL_TREE
1375 && DECL_CXX_CONSTRUCTOR_P (fn
)
1376 && TREE_CODE (TREE_TYPE (fn
)) == METHOD_TYPE
1377 && gimple_call_num_args (stmt
))
1379 tree op
= walk_ssa_copies (gimple_call_arg (stmt
, 0));
1380 tree type
= method_class_type (TREE_TYPE (fn
));
1381 HOST_WIDE_INT offset
= 0, size
, max_size
;
1385 fprintf (dump_file
, " Checking constructor call: ");
1386 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1389 /* See if THIS parameter seems like instance pointer. */
1390 if (TREE_CODE (op
) == ADDR_EXPR
)
1392 op
= get_ref_base_and_extent (TREE_OPERAND (op
, 0),
1393 &offset
, &size
, &max_size
);
1394 if (size
!= max_size
|| max_size
== -1)
1396 tci
->speculative
= true;
1399 if (op
&& TREE_CODE (op
) == MEM_REF
)
1401 if (!tree_fits_shwi_p (TREE_OPERAND (op
, 1)))
1403 tci
->speculative
= true;
1406 offset
+= tree_to_shwi (TREE_OPERAND (op
, 1))
1408 op
= TREE_OPERAND (op
, 0);
1410 else if (DECL_P (op
))
1414 tci
->speculative
= true;
1417 op
= walk_ssa_copies (op
);
1419 if (operand_equal_p (op
, tci
->instance
, 0)
1421 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
1422 && tree_fits_shwi_p (TYPE_SIZE (type
))
1423 && tree_to_shwi (TYPE_SIZE (type
)) + offset
> tci
->offset
)
1425 record_known_type (tci
, type
, tci
->offset
- offset
);
1429 /* Calls may possibly change dynamic type by placement new. Assume
1430 it will not happen, but make result speculative only. */
1433 fprintf (dump_file
, " Function call may change dynamic type:");
1434 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1436 tci
->speculative
= true;
1439 /* Check for inlined virtual table store. */
1440 else if (noncall_stmt_may_be_vtbl_ptr_store (stmt
))
1443 HOST_WIDE_INT offset
= 0;
1446 fprintf (dump_file
, " Checking vtbl store: ");
1447 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1450 type
= extr_type_from_vtbl_ptr_store (stmt
, tci
, &offset
);
1451 if (type
== error_mark_node
)
1453 gcc_assert (!type
|| TYPE_MAIN_VARIANT (type
) == type
);
1457 fprintf (dump_file
, " Unanalyzed store may change type.\n");
1458 tci
->seen_unanalyzed_store
= true;
1459 tci
->speculative
= true;
1462 record_known_type (tci
, type
, offset
);
1469 /* THIS is polymorphic call context obtained from get_polymorphic_context.
1470 OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
1471 INSTANCE is pointer to the outer instance as returned by
1472 get_polymorphic_context. To avoid creation of temporary expressions,
1473 INSTANCE may also be an declaration of get_polymorphic_context found the
1474 value to be in static storage.
1476 If the type of instance is not fully determined
1477 (either OUTER_TYPE is unknown or MAYBE_IN_CONSTRUCTION/INCLUDE_DERIVED_TYPES
1478 is set), try to walk memory writes and find the actual construction of the
1481 Return true if memory is unchanged from function entry.
1483 We do not include this analysis in the context analysis itself, because
1484 it needs memory SSA to be fully built and the walk may be expensive.
1485 So it is not suitable for use withing fold_stmt and similar uses. */
1488 ipa_polymorphic_call_context::get_dynamic_type (tree instance
,
1493 struct type_change_info tci
;
1495 bool function_entry_reached
= false;
1496 tree instance_ref
= NULL
;
1498 /* Remember OFFSET before it is modified by restrict_to_inner_class.
1499 This is because we do not update INSTANCE when walking inwards. */
1500 HOST_WIDE_INT instance_offset
= offset
;
1503 otr_type
= TYPE_MAIN_VARIANT (otr_type
);
1505 /* Walk into inner type. This may clear maybe_derived_type and save us
1506 from useless work. It also makes later comparsions with static type
1508 if (outer_type
&& otr_type
)
1510 if (!restrict_to_inner_class (otr_type
))
1514 if (!maybe_in_construction
&& !maybe_derived_type
)
1517 /* We need to obtain refernce to virtual table pointer. It is better
1518 to look it up in the code rather than build our own. This require bit
1519 of pattern matching, but we end up verifying that what we found is
1522 What we pattern match is:
1524 tmp = instance->_vptr.A; // vtbl ptr load
1525 tmp2 = tmp[otr_token]; // vtable lookup
1526 OBJ_TYPE_REF(tmp2;instance->0) (instance);
1528 We want to start alias oracle walk from vtbl pointer load,
1529 but we may not be able to identify it, for example, when PRE moved the
1532 if (gimple_code (call
) == GIMPLE_CALL
)
1534 tree ref
= gimple_call_fn (call
);
1535 HOST_WIDE_INT offset2
, size
, max_size
;
1537 if (TREE_CODE (ref
) == OBJ_TYPE_REF
)
1539 ref
= OBJ_TYPE_REF_EXPR (ref
);
1540 ref
= walk_ssa_copies (ref
);
1542 /* Check if definition looks like vtable lookup. */
1543 if (TREE_CODE (ref
) == SSA_NAME
1544 && !SSA_NAME_IS_DEFAULT_DEF (ref
)
1545 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref
))
1546 && TREE_CODE (gimple_assign_rhs1
1547 (SSA_NAME_DEF_STMT (ref
))) == MEM_REF
)
1549 ref
= get_base_address
1550 (TREE_OPERAND (gimple_assign_rhs1
1551 (SSA_NAME_DEF_STMT (ref
)), 0));
1552 ref
= walk_ssa_copies (ref
);
1553 /* Find base address of the lookup and see if it looks like
1555 if (TREE_CODE (ref
) == SSA_NAME
1556 && !SSA_NAME_IS_DEFAULT_DEF (ref
)
1557 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref
)))
1559 tree ref_exp
= gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref
));
1560 tree base_ref
= get_ref_base_and_extent
1561 (ref_exp
, &offset2
, &size
, &max_size
);
1563 /* Finally verify that what we found looks like read from OTR_OBJECT
1564 or from INSTANCE with offset OFFSET. */
1566 && ((TREE_CODE (base_ref
) == MEM_REF
1567 && ((offset2
== instance_offset
1568 && TREE_OPERAND (base_ref
, 0) == instance
)
1569 || (!offset2
&& TREE_OPERAND (base_ref
, 0) == otr_object
)))
1570 || (DECL_P (instance
) && base_ref
== instance
1571 && offset2
== instance_offset
)))
1573 stmt
= SSA_NAME_DEF_STMT (ref
);
1574 instance_ref
= ref_exp
;
1581 /* If we failed to look up the refernece in code, build our own. */
1584 /* If the statement in question does not use memory, we can't tell
1586 if (!gimple_vuse (stmt
))
1588 ao_ref_init_from_ptr_and_size (&ao
, otr_object
, NULL
);
1591 /* Otherwise use the real reference. */
1592 ao_ref_init (&ao
, instance_ref
);
1594 /* We look for vtbl pointer read. */
1595 ao
.size
= POINTER_SIZE
;
1596 ao
.max_size
= ao
.size
;
1599 = get_deref_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type
))));
1603 fprintf (dump_file
, "Determining dynamic type for call: ");
1604 print_gimple_stmt (dump_file
, call
, 0, 0);
1605 fprintf (dump_file
, " Starting walk at: ");
1606 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1607 fprintf (dump_file
, " instance pointer: ");
1608 print_generic_expr (dump_file
, otr_object
, TDF_SLIM
);
1609 fprintf (dump_file
, " Outer instance pointer: ");
1610 print_generic_expr (dump_file
, instance
, TDF_SLIM
);
1611 fprintf (dump_file
, " offset: %i (bits)", (int)offset
);
1612 fprintf (dump_file
, " vtbl reference: ");
1613 print_generic_expr (dump_file
, instance_ref
, TDF_SLIM
);
1614 fprintf (dump_file
, "\n");
1617 tci
.offset
= offset
;
1618 tci
.instance
= instance
;
1619 tci
.vtbl_ptr_ref
= instance_ref
;
1620 gcc_assert (TREE_CODE (instance
) != MEM_REF
);
1621 tci
.known_current_type
= NULL_TREE
;
1622 tci
.known_current_offset
= 0;
1623 tci
.otr_type
= otr_type
;
1624 tci
.type_maybe_changed
= false;
1625 tci
.multiple_types_encountered
= false;
1626 tci
.speculative
= false;
1627 tci
.seen_unanalyzed_store
= false;
1629 walk_aliased_vdefs (&ao
, gimple_vuse (stmt
), check_stmt_for_type_change
,
1630 &tci
, NULL
, &function_entry_reached
);
1632 /* If we did not find any type changing statements, we may still drop
1633 maybe_in_construction flag if the context already have outer type.
1635 Here we make special assumptions about both constructors and
1636 destructors which are all the functions that are allowed to alter the
1637 VMT pointers. It assumes that destructors begin with assignment into
1638 all VMT pointers and that constructors essentially look in the
1641 1) The very first thing they do is that they call constructors of
1642 ancestor sub-objects that have them.
1644 2) Then VMT pointers of this and all its ancestors is set to new
1645 values corresponding to the type corresponding to the constructor.
1647 3) Only afterwards, other stuff such as constructor of member
1648 sub-objects and the code written by the user is run. Only this may
1649 include calling virtual functions, directly or indirectly.
1651 4) placement new can not be used to change type of non-POD statically
1652 allocated variables.
1654 There is no way to call a constructor of an ancestor sub-object in any
1657 This means that we do not have to care whether constructors get the
1658 correct type information because they will always change it (in fact,
1659 if we define the type to be given by the VMT pointer, it is undefined).
1661 The most important fact to derive from the above is that if, for some
1662 statement in the section 3, we try to detect whether the dynamic type
1663 has changed, we can safely ignore all calls as we examine the function
1664 body backwards until we reach statements in section 2 because these
1665 calls cannot be ancestor constructors or destructors (if the input is
1666 not bogus) and so do not change the dynamic type (this holds true only
1667 for automatically allocated objects but at the moment we devirtualize
1668 only these). We then must detect that statements in section 2 change
1669 the dynamic type and can try to derive the new type. That is enough
1670 and we can stop, we will never see the calls into constructors of
1671 sub-objects in this code.
1673 Therefore if the static outer type was found (outer_type)
1674 we can safely ignore tci.speculative that is set on calls and give up
1675 only if there was dyanmic type store that may affect given variable
1676 (seen_unanalyzed_store) */
1678 if (!tci
.type_maybe_changed
1681 && !tci
.seen_unanalyzed_store
1682 && !tci
.multiple_types_encountered
1683 && offset
== tci
.offset
1684 && types_same_for_odr (tci
.known_current_type
,
1687 if (!outer_type
|| tci
.seen_unanalyzed_store
)
1689 if (maybe_in_construction
)
1690 maybe_in_construction
= false;
1692 fprintf (dump_file
, " No dynamic type change found.\n");
1696 if (tci
.known_current_type
1697 && !function_entry_reached
1698 && !tci
.multiple_types_encountered
)
1700 if (!tci
.speculative
)
1702 outer_type
= TYPE_MAIN_VARIANT (tci
.known_current_type
);
1703 offset
= tci
.known_current_offset
;
1705 maybe_in_construction
= false;
1706 maybe_derived_type
= false;
1708 fprintf (dump_file
, " Determined dynamic type.\n");
1710 else if (!speculative_outer_type
1711 || speculative_maybe_derived_type
)
1713 speculative_outer_type
= TYPE_MAIN_VARIANT (tci
.known_current_type
);
1714 speculative_offset
= tci
.known_current_offset
;
1715 speculative_maybe_derived_type
= false;
1717 fprintf (dump_file
, " Determined speculative dynamic type.\n");
1722 fprintf (dump_file
, " Found multiple types%s%s\n",
1723 function_entry_reached
? " (function entry reached)" : "",
1724 function_entry_reached
? " (multiple types encountered)" : "");
1730 /* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
1731 seems consistent (and useful) with what we already have in the non-speculative context. */
1734 ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type
,
1735 HOST_WIDE_INT spec_offset
,
1736 bool spec_maybe_derived_type
,
1737 tree otr_type
) const
1739 if (!flag_devirtualize_speculatively
)
1742 /* Non-polymorphic types are useless for deriving likely polymorphic
1744 if (!spec_outer_type
|| !contains_polymorphic_type_p (spec_outer_type
))
1747 /* If we know nothing, speculation is always good. */
1751 /* Speculation is only useful to avoid derived types.
1752 This is not 100% true for placement new, where the outer context may
1753 turn out to be useless, but ignore these for now. */
1754 if (!maybe_derived_type
)
1757 /* If types agrees, speculation is consistent, but it makes sense only
1758 when it says something new. */
1759 if (types_must_be_same_for_odr (spec_outer_type
, outer_type
))
1760 return maybe_derived_type
&& !spec_maybe_derived_type
;
1762 /* If speculation does not contain the type in question, ignore it. */
1764 && !contains_type_p (spec_outer_type
, spec_offset
, otr_type
, false, true))
1767 /* If outer type already contains speculation as a filed,
1768 it is useless. We already know from OUTER_TYPE
1769 SPEC_TYPE and that it is not in the construction. */
1770 if (contains_type_p (outer_type
, offset
- spec_offset
,
1771 spec_outer_type
, false, false))
1774 /* If speculative outer type is not more specified than outer
1776 We can only decide this safely if we can compare types with OUTER_TYPE.
1778 if ((!in_lto_p
|| odr_type_p (outer_type
))
1779 && !contains_type_p (spec_outer_type
,
1780 spec_offset
- offset
,
1786 /* Improve THIS with speculation described by NEW_OUTER_TYPE, NEW_OFFSET,
1787 NEW_MAYBE_DERIVED_TYPE
1788 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
1791 ipa_polymorphic_call_context::combine_speculation_with
1792 (tree new_outer_type
, HOST_WIDE_INT new_offset
, bool new_maybe_derived_type
,
1795 if (!new_outer_type
)
1798 /* restrict_to_inner_class may eliminate wrong speculation making our job
1801 restrict_to_inner_class (otr_type
);
1803 if (!speculation_consistent_p (new_outer_type
, new_offset
,
1804 new_maybe_derived_type
, otr_type
))
1807 /* New speculation is a win in case we have no speculation or new
1808 speculation does not consider derivations. */
1809 if (!speculative_outer_type
1810 || (speculative_maybe_derived_type
1811 && !new_maybe_derived_type
))
1813 speculative_outer_type
= new_outer_type
;
1814 speculative_offset
= new_offset
;
1815 speculative_maybe_derived_type
= new_maybe_derived_type
;
1818 else if (types_must_be_same_for_odr (speculative_outer_type
,
1821 if (speculative_offset
!= new_offset
)
1823 /* OK we have two contexts that seems valid but they disagree,
1826 This is not a lattice operation, so we may want to drop it later. */
1827 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1829 "Speculative outer types match, "
1830 "offset mismatch -> invalid speculation\n");
1831 clear_speculation ();
1836 if (speculative_maybe_derived_type
&& !new_maybe_derived_type
)
1838 speculative_maybe_derived_type
= false;
1845 /* Choose type that contains the other. This one either contains the outer
1846 as a field (thus giving exactly one target) or is deeper in the type
1848 else if (speculative_outer_type
1849 && speculative_maybe_derived_type
1850 && (new_offset
> speculative_offset
1851 || (new_offset
== speculative_offset
1852 && contains_type_p (new_outer_type
,
1853 0, speculative_outer_type
, false))))
1855 tree old_outer_type
= speculative_outer_type
;
1856 HOST_WIDE_INT old_offset
= speculative_offset
;
1857 bool old_maybe_derived_type
= speculative_maybe_derived_type
;
1859 speculative_outer_type
= new_outer_type
;
1860 speculative_offset
= new_offset
;
1861 speculative_maybe_derived_type
= new_maybe_derived_type
;
1864 restrict_to_inner_class (otr_type
);
1866 /* If the speculation turned out to make no sense, revert to sensible
1868 if (!speculative_outer_type
)
1870 speculative_outer_type
= old_outer_type
;
1871 speculative_offset
= old_offset
;
1872 speculative_maybe_derived_type
= old_maybe_derived_type
;
1875 return (old_offset
!= speculative_offset
1876 || old_maybe_derived_type
!= speculative_maybe_derived_type
1877 || types_must_be_same_for_odr (speculative_outer_type
,
1883 /* Make speculation less specific so
1884 NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included.
1885 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
1888 ipa_polymorphic_call_context::meet_speculation_with
1889 (tree new_outer_type
, HOST_WIDE_INT new_offset
, bool new_maybe_derived_type
,
1892 if (!new_outer_type
&& speculative_outer_type
)
1894 clear_speculation ();
1898 /* restrict_to_inner_class may eliminate wrong speculation making our job
1901 restrict_to_inner_class (otr_type
);
1903 if (!speculative_outer_type
1904 || !speculation_consistent_p (speculative_outer_type
,
1906 speculative_maybe_derived_type
,
1910 if (!speculation_consistent_p (new_outer_type
, new_offset
,
1911 new_maybe_derived_type
, otr_type
))
1913 clear_speculation ();
1917 else if (types_must_be_same_for_odr (speculative_outer_type
,
1920 if (speculative_offset
!= new_offset
)
1922 clear_speculation ();
1927 if (!speculative_maybe_derived_type
&& new_maybe_derived_type
)
1929 speculative_maybe_derived_type
= true;
1936 /* See if one type contains the other as a field (not base). */
1937 else if (contains_type_p (new_outer_type
, new_offset
- speculative_offset
,
1938 speculative_outer_type
, false, false))
1940 else if (contains_type_p (speculative_outer_type
,
1941 speculative_offset
- new_offset
,
1942 new_outer_type
, false, false))
1944 speculative_outer_type
= new_outer_type
;
1945 speculative_offset
= new_offset
;
1946 speculative_maybe_derived_type
= new_maybe_derived_type
;
1949 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
1950 else if (contains_type_p (new_outer_type
,
1951 new_offset
- speculative_offset
,
1952 speculative_outer_type
, false, true))
1954 if (!speculative_maybe_derived_type
)
1956 speculative_maybe_derived_type
= true;
1961 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
1962 else if (contains_type_p (speculative_outer_type
,
1963 speculative_offset
- new_offset
, new_outer_type
, false, true))
1965 speculative_outer_type
= new_outer_type
;
1966 speculative_offset
= new_offset
;
1967 speculative_maybe_derived_type
= true;
1972 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1973 fprintf (dump_file
, "Giving up on speculative meet\n");
1974 clear_speculation ();
1979 /* Assume that both THIS and a given context is valid and strenghten THIS
1980 if possible. Return true if any strenghtening was made.
1981 If actual type the context is being used in is known, OTR_TYPE should be
1982 set accordingly. This improves quality of combined result. */
1985 ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx
,
1988 bool updated
= false;
1990 if (ctx
.useless_p () || invalid
)
1993 /* Restricting context to inner type makes merging easier, however do not
1994 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
1995 if (otr_type
&& !invalid
&& !ctx
.invalid
)
1997 restrict_to_inner_class (otr_type
);
1998 ctx
.restrict_to_inner_class (otr_type
);
2003 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2005 fprintf (dump_file
, "Polymorphic call context combine:");
2007 fprintf (dump_file
, "With context: ");
2008 ctx
.dump (dump_file
);
2011 fprintf (dump_file
, "To be used with type: ");
2012 print_generic_expr (dump_file
, otr_type
, TDF_SLIM
);
2013 fprintf (dump_file
, "\n");
2017 /* If call is known to be invalid, we are done. */
2020 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2021 fprintf (dump_file
, "-> Invalid context\n");
2025 if (!ctx
.outer_type
)
2027 else if (!outer_type
)
2029 outer_type
= ctx
.outer_type
;
2030 offset
= ctx
.offset
;
2031 dynamic
= ctx
.dynamic
;
2032 maybe_in_construction
= ctx
.maybe_in_construction
;
2033 maybe_derived_type
= ctx
.maybe_derived_type
;
2036 /* If types are known to be same, merging is quite easy. */
2037 else if (types_must_be_same_for_odr (outer_type
, ctx
.outer_type
))
2039 if (offset
!= ctx
.offset
2040 && TYPE_SIZE (outer_type
)
2041 && TREE_CODE (TYPE_SIZE (outer_type
)) == INTEGER_CST
)
2043 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2044 fprintf (dump_file
, "Outer types match, offset mismatch -> invalid\n");
2045 clear_speculation ();
2046 clear_outer_type ();
2050 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2051 fprintf (dump_file
, "Outer types match, merging flags\n");
2052 if (maybe_in_construction
&& !ctx
.maybe_in_construction
)
2055 maybe_in_construction
= false;
2057 if (maybe_derived_type
&& !ctx
.maybe_derived_type
)
2060 maybe_derived_type
= false;
2062 if (dynamic
&& !ctx
.dynamic
)
2068 /* If we know the type precisely, there is not much to improve. */
2069 else if (!maybe_derived_type
&& !maybe_in_construction
2070 && !ctx
.maybe_derived_type
&& !ctx
.maybe_in_construction
)
2072 /* It may be easy to check if second context permits the first
2073 and set INVALID otherwise. This is not easy to do in general;
2074 contains_type_p may return false negatives for non-comparable
2077 If OTR_TYPE is known, we however can expect that
2078 restrict_to_inner_class should have discovered the same base
2080 if (otr_type
&& !ctx
.maybe_in_construction
&& !ctx
.maybe_derived_type
)
2082 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2083 fprintf (dump_file
, "Contextes disagree -> invalid\n");
2087 /* See if one type contains the other as a field (not base).
2088 In this case we want to choose the wider type, because it contains
2089 more information. */
2090 else if (contains_type_p (ctx
.outer_type
, ctx
.offset
- offset
,
2091 outer_type
, false, false))
2093 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2094 fprintf (dump_file
, "Second type contain the first as a field\n");
2096 if (maybe_derived_type
)
2098 outer_type
= ctx
.outer_type
;
2099 maybe_derived_type
= ctx
.maybe_derived_type
;
2100 offset
= ctx
.offset
;
2101 dynamic
= ctx
.dynamic
;
2105 /* If we do not know how the context is being used, we can
2106 not clear MAYBE_IN_CONSTRUCTION because it may be offseted
2107 to other component of OUTER_TYPE later and we know nothing
2109 if (otr_type
&& maybe_in_construction
2110 && !ctx
.maybe_in_construction
)
2112 maybe_in_construction
= false;
2116 else if (contains_type_p (outer_type
, offset
- ctx
.offset
,
2117 ctx
.outer_type
, false, false))
2119 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2120 fprintf (dump_file
, "First type contain the second as a field\n");
2122 if (otr_type
&& maybe_in_construction
2123 && !ctx
.maybe_in_construction
)
2125 maybe_in_construction
= false;
2129 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
2130 else if (contains_type_p (ctx
.outer_type
,
2131 ctx
.offset
- offset
, outer_type
, false, true))
2133 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2134 fprintf (dump_file
, "First type is base of second\n");
2135 if (!maybe_derived_type
)
2137 if (!ctx
.maybe_in_construction
2138 && types_odr_comparable (outer_type
, ctx
.outer_type
))
2140 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2141 fprintf (dump_file
, "Second context does not permit base -> invalid\n");
2145 /* Pick variant deeper in the hiearchy. */
2148 outer_type
= ctx
.outer_type
;
2149 maybe_in_construction
= ctx
.maybe_in_construction
;
2150 maybe_derived_type
= ctx
.maybe_derived_type
;
2151 offset
= ctx
.offset
;
2152 dynamic
= ctx
.dynamic
;
2156 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
2157 else if (contains_type_p (outer_type
,
2158 offset
- ctx
.offset
, ctx
.outer_type
, false, true))
2160 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2161 fprintf (dump_file
, "Second type is base of first\n");
2162 if (!ctx
.maybe_derived_type
)
2164 if (!maybe_in_construction
2165 && types_odr_comparable (outer_type
, ctx
.outer_type
))
2167 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2168 fprintf (dump_file
, "First context does not permit base -> invalid\n");
2171 /* Pick the base type. */
2172 else if (maybe_in_construction
)
2174 outer_type
= ctx
.outer_type
;
2175 maybe_in_construction
= ctx
.maybe_in_construction
;
2176 maybe_derived_type
= ctx
.maybe_derived_type
;
2177 offset
= ctx
.offset
;
2178 dynamic
= ctx
.dynamic
;
2183 /* TODO handle merging using hiearchy. */
2184 else if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2185 fprintf (dump_file
, "Giving up on merge\n");
2187 updated
|= combine_speculation_with (ctx
.speculative_outer_type
,
2188 ctx
.speculative_offset
,
2189 ctx
.speculative_maybe_derived_type
,
2192 if (updated
&& dump_file
&& (dump_flags
& TDF_DETAILS
))
2194 fprintf (dump_file
, "Updated as: ");
2196 fprintf (dump_file
, "\n");
2202 clear_speculation ();
2203 clear_outer_type ();
2207 /* Take non-speculative info, merge it with speculative and clear speculation.
2208 Used when we no longer manage to keep track of actual outer type, but we
2209 think it is still there.
2211 If OTR_TYPE is set, the transformation can be done more effectively assuming
2212 that context is going to be used only that way. */
2215 ipa_polymorphic_call_context::make_speculative (tree otr_type
)
2217 tree spec_outer_type
= outer_type
;
2218 HOST_WIDE_INT spec_offset
= offset
;
2219 bool spec_maybe_derived_type
= maybe_derived_type
;
2224 clear_outer_type ();
2225 clear_speculation ();
2230 clear_outer_type ();
2231 combine_speculation_with (spec_outer_type
, spec_offset
,
2232 spec_maybe_derived_type
,
2236 /* Use when we can not track dynamic type change. This speculatively assume
2237 type change is not happening. */
2240 ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor
,
2244 make_speculative (otr_type
);
2245 else if (in_poly_cdtor
)
2246 maybe_in_construction
= true;
2249 /* Return TRUE if this context conveys the same information as OTHER. */
2252 ipa_polymorphic_call_context::equal_to
2253 (const ipa_polymorphic_call_context
&x
) const
2256 return x
.useless_p ();
2259 if (x
.useless_p () || x
.invalid
)
2265 || !types_odr_comparable (outer_type
, x
.outer_type
)
2266 || !types_same_for_odr (outer_type
, x
.outer_type
)
2267 || offset
!= x
.offset
2268 || maybe_in_construction
!= x
.maybe_in_construction
2269 || maybe_derived_type
!= x
.maybe_derived_type
2270 || dynamic
!= x
.dynamic
)
2273 else if (x
.outer_type
)
2277 if (speculative_outer_type
2278 && speculation_consistent_p (speculative_outer_type
, speculative_offset
,
2279 speculative_maybe_derived_type
, NULL_TREE
))
2281 if (!x
.speculative_outer_type
)
2284 if (!types_odr_comparable (speculative_outer_type
,
2285 x
.speculative_outer_type
)
2286 || !types_same_for_odr (speculative_outer_type
,
2287 x
.speculative_outer_type
)
2288 || speculative_offset
!= x
.speculative_offset
2289 || speculative_maybe_derived_type
!= x
.speculative_maybe_derived_type
)
2292 else if (x
.speculative_outer_type
2293 && x
.speculation_consistent_p (x
.speculative_outer_type
,
2294 x
.speculative_offset
,
2295 x
.speculative_maybe_derived_type
,
2302 /* Modify context to be strictly less restrictive than CTX. */
2305 ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx
,
2308 bool updated
= false;
2310 if (useless_p () || ctx
.invalid
)
2313 /* Restricting context to inner type makes merging easier, however do not
2314 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
2315 if (otr_type
&& !useless_p () && !ctx
.useless_p ())
2317 restrict_to_inner_class (otr_type
);
2318 ctx
.restrict_to_inner_class (otr_type
);
2326 if (ctx
.useless_p () || invalid
)
2332 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2334 fprintf (dump_file
, "Polymorphic call context meet:");
2336 fprintf (dump_file
, "With context: ");
2337 ctx
.dump (dump_file
);
2340 fprintf (dump_file
, "To be used with type: ");
2341 print_generic_expr (dump_file
, otr_type
, TDF_SLIM
);
2342 fprintf (dump_file
, "\n");
2346 if (!dynamic
&& ctx
.dynamic
)
2352 /* If call is known to be invalid, we are done. */
2355 else if (!ctx
.outer_type
)
2357 clear_outer_type ();
2360 /* If types are known to be same, merging is quite easy. */
2361 else if (types_must_be_same_for_odr (outer_type
, ctx
.outer_type
))
2363 if (offset
!= ctx
.offset
2364 && TYPE_SIZE (outer_type
)
2365 && TREE_CODE (TYPE_SIZE (outer_type
)) == INTEGER_CST
)
2367 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2368 fprintf (dump_file
, "Outer types match, offset mismatch -> clearing\n");
2369 clear_outer_type ();
2372 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2373 fprintf (dump_file
, "Outer types match, merging flags\n");
2374 if (!maybe_in_construction
&& ctx
.maybe_in_construction
)
2377 maybe_in_construction
= true;
2379 if (!maybe_derived_type
&& ctx
.maybe_derived_type
)
2382 maybe_derived_type
= true;
2384 if (!dynamic
&& ctx
.dynamic
)
2390 /* See if one type contains the other as a field (not base). */
2391 else if (contains_type_p (ctx
.outer_type
, ctx
.offset
- offset
,
2392 outer_type
, false, false))
2394 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2395 fprintf (dump_file
, "Second type contain the first as a field\n");
2397 /* The second type is more specified, so we keep the first.
2398 We need to set DYNAMIC flag to avoid declaring context INVALID
2399 of OFFSET ends up being out of range. */
2403 && (!TYPE_SIZE (ctx
.outer_type
)
2404 || !TYPE_SIZE (outer_type
)
2405 || !operand_equal_p (TYPE_SIZE (ctx
.outer_type
),
2406 TYPE_SIZE (outer_type
), 0)))))
2412 else if (contains_type_p (outer_type
, offset
- ctx
.offset
,
2413 ctx
.outer_type
, false, false))
2415 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2416 fprintf (dump_file
, "First type contain the second as a field\n");
2421 && (!TYPE_SIZE (ctx
.outer_type
)
2422 || !TYPE_SIZE (outer_type
)
2423 || !operand_equal_p (TYPE_SIZE (ctx
.outer_type
),
2424 TYPE_SIZE (outer_type
), 0)))))
2426 outer_type
= ctx
.outer_type
;
2427 offset
= ctx
.offset
;
2428 dynamic
= ctx
.dynamic
;
2429 maybe_in_construction
= ctx
.maybe_in_construction
;
2430 maybe_derived_type
= ctx
.maybe_derived_type
;
2433 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
2434 else if (contains_type_p (ctx
.outer_type
,
2435 ctx
.offset
- offset
, outer_type
, false, true))
2437 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2438 fprintf (dump_file
, "First type is base of second\n");
2439 if (!maybe_derived_type
)
2441 maybe_derived_type
= true;
2444 if (!maybe_in_construction
&& ctx
.maybe_in_construction
)
2446 maybe_in_construction
= true;
2449 if (!dynamic
&& ctx
.dynamic
)
2455 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
2456 else if (contains_type_p (outer_type
,
2457 offset
- ctx
.offset
, ctx
.outer_type
, false, true))
2459 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2460 fprintf (dump_file
, "Second type is base of first\n");
2461 outer_type
= ctx
.outer_type
;
2462 offset
= ctx
.offset
;
2464 if (!maybe_derived_type
)
2465 maybe_derived_type
= true;
2466 if (!maybe_in_construction
&& ctx
.maybe_in_construction
)
2467 maybe_in_construction
= true;
2468 if (!dynamic
&& ctx
.dynamic
)
2471 /* TODO handle merging using hiearchy. */
2474 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2475 fprintf (dump_file
, "Giving up on meet\n");
2476 clear_outer_type ();
2480 updated
|= meet_speculation_with (ctx
.speculative_outer_type
,
2481 ctx
.speculative_offset
,
2482 ctx
.speculative_maybe_derived_type
,
2485 if (updated
&& dump_file
&& (dump_flags
& TDF_DETAILS
))
2487 fprintf (dump_file
, "Updated as: ");
2489 fprintf (dump_file
, "\n");