annotate gcc/ipa-polymorphic-call.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Analysis of polymorphic call context.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2013-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Jan Hubicka
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "backend.h"
kono
parents:
diff changeset
25 #include "rtl.h"
kono
parents:
diff changeset
26 #include "tree.h"
kono
parents:
diff changeset
27 #include "gimple.h"
kono
parents:
diff changeset
28 #include "tree-pass.h"
kono
parents:
diff changeset
29 #include "tree-ssa-operands.h"
kono
parents:
diff changeset
30 #include "streamer-hooks.h"
kono
parents:
diff changeset
31 #include "cgraph.h"
kono
parents:
diff changeset
32 #include "data-streamer.h"
kono
parents:
diff changeset
33 #include "diagnostic.h"
kono
parents:
diff changeset
34 #include "alias.h"
kono
parents:
diff changeset
35 #include "fold-const.h"
kono
parents:
diff changeset
36 #include "calls.h"
kono
parents:
diff changeset
37 #include "ipa-utils.h"
kono
parents:
diff changeset
38 #include "tree-dfa.h"
kono
parents:
diff changeset
39 #include "gimple-pretty-print.h"
kono
parents:
diff changeset
40 #include "tree-into-ssa.h"
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 /* Return true when TYPE contains an polymorphic type and thus is interesting
kono
parents:
diff changeset
43 for devirtualization machinery. */
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 static bool contains_type_p (tree, HOST_WIDE_INT, tree,
kono
parents:
diff changeset
46 bool consider_placement_new = true,
kono
parents:
diff changeset
47 bool consider_bases = true);
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 bool
kono
parents:
diff changeset
50 contains_polymorphic_type_p (const_tree type)
kono
parents:
diff changeset
51 {
kono
parents:
diff changeset
52 type = TYPE_MAIN_VARIANT (type);
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
55 {
kono
parents:
diff changeset
56 if (TYPE_BINFO (type)
kono
parents:
diff changeset
57 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
58 return true;
kono
parents:
diff changeset
59 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
kono
parents:
diff changeset
60 if (TREE_CODE (fld) == FIELD_DECL
kono
parents:
diff changeset
61 && !DECL_ARTIFICIAL (fld)
kono
parents:
diff changeset
62 && contains_polymorphic_type_p (TREE_TYPE (fld)))
kono
parents:
diff changeset
63 return true;
kono
parents:
diff changeset
64 return false;
kono
parents:
diff changeset
65 }
kono
parents:
diff changeset
66 if (TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
67 return contains_polymorphic_type_p (TREE_TYPE (type));
kono
parents:
diff changeset
68 return false;
kono
parents:
diff changeset
69 }
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 /* Return true if it seems valid to use placement new to build EXPECTED_TYPE
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
72 at position CUR_OFFSET within TYPE.
111
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 POD can be changed to an instance of a polymorphic type by
kono
parents:
diff changeset
75 placement new. Here we play safe and assume that any
kono
parents:
diff changeset
76 non-polymorphic type is POD. */
kono
parents:
diff changeset
77 bool
kono
parents:
diff changeset
78 possible_placement_new (tree type, tree expected_type,
kono
parents:
diff changeset
79 HOST_WIDE_INT cur_offset)
kono
parents:
diff changeset
80 {
kono
parents:
diff changeset
81 if (cur_offset < 0)
kono
parents:
diff changeset
82 return true;
kono
parents:
diff changeset
83 return ((TREE_CODE (type) != RECORD_TYPE
kono
parents:
diff changeset
84 || !TYPE_BINFO (type)
kono
parents:
diff changeset
85 || cur_offset >= POINTER_SIZE
kono
parents:
diff changeset
86 || !polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
87 && (!TYPE_SIZE (type)
kono
parents:
diff changeset
88 || !tree_fits_shwi_p (TYPE_SIZE (type))
kono
parents:
diff changeset
89 || (cur_offset
kono
parents:
diff changeset
90 + (expected_type ? tree_to_uhwi (TYPE_SIZE (expected_type))
kono
parents:
diff changeset
91 : POINTER_SIZE)
kono
parents:
diff changeset
92 <= tree_to_uhwi (TYPE_SIZE (type)))));
kono
parents:
diff changeset
93 }
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 /* THIS->OUTER_TYPE is a type of memory object where object of OTR_TYPE
kono
parents:
diff changeset
96 is contained at THIS->OFFSET. Walk the memory representation of
kono
parents:
diff changeset
97 THIS->OUTER_TYPE and find the outermost class type that match
kono
parents:
diff changeset
98 OTR_TYPE or contain OTR_TYPE as a base. Update THIS
kono
parents:
diff changeset
99 to represent it.
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 If OTR_TYPE is NULL, just find outermost polymorphic type with
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
102 virtual table present at position OFFSET.
111
kono
parents:
diff changeset
103
kono
parents:
diff changeset
104 For example when THIS represents type
kono
parents:
diff changeset
105 class A
kono
parents:
diff changeset
106 {
kono
parents:
diff changeset
107 int a;
kono
parents:
diff changeset
108 class B b;
kono
parents:
diff changeset
109 }
kono
parents:
diff changeset
110 and we look for type at offset sizeof(int), we end up with B and offset 0.
kono
parents:
diff changeset
111 If the same is produced by multiple inheritance, we end up with A and offset
kono
parents:
diff changeset
112 sizeof(int).
kono
parents:
diff changeset
113
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
114 If we cannot find corresponding class, give up by setting
111
kono
parents:
diff changeset
115 THIS->OUTER_TYPE to OTR_TYPE and THIS->OFFSET to NULL.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
116 Return true when lookup was successful.
111
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
kono
parents:
diff changeset
119 valid only via allocation of new polymorphic type inside by means
kono
parents:
diff changeset
120 of placement new.
kono
parents:
diff changeset
121
kono
parents:
diff changeset
122 When CONSIDER_BASES is false, only look for actual fields, not base types
kono
parents:
diff changeset
123 of TYPE. */
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 bool
kono
parents:
diff changeset
126 ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
kono
parents:
diff changeset
127 bool consider_placement_new,
kono
parents:
diff changeset
128 bool consider_bases)
kono
parents:
diff changeset
129 {
kono
parents:
diff changeset
130 tree type = outer_type;
kono
parents:
diff changeset
131 HOST_WIDE_INT cur_offset = offset;
kono
parents:
diff changeset
132 bool speculative = false;
kono
parents:
diff changeset
133 bool size_unknown = false;
kono
parents:
diff changeset
134 unsigned HOST_WIDE_INT otr_type_size = POINTER_SIZE;
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set. */
kono
parents:
diff changeset
137 if (!outer_type)
kono
parents:
diff changeset
138 {
kono
parents:
diff changeset
139 clear_outer_type (otr_type);
kono
parents:
diff changeset
140 type = otr_type;
kono
parents:
diff changeset
141 cur_offset = 0;
kono
parents:
diff changeset
142 }
kono
parents:
diff changeset
143 /* See if OFFSET points inside OUTER_TYPE. If it does not, we know
kono
parents:
diff changeset
144 that the context is either invalid, or the instance type must be
kono
parents:
diff changeset
145 derived from OUTER_TYPE.
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 Because the instance type may contain field whose type is of OUTER_TYPE,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
148 we cannot derive any effective information about it.
111
kono
parents:
diff changeset
149
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
150 TODO: In the case we know all derived types, we can definitely do better
111
kono
parents:
diff changeset
151 here. */
kono
parents:
diff changeset
152 else if (TYPE_SIZE (outer_type)
kono
parents:
diff changeset
153 && tree_fits_shwi_p (TYPE_SIZE (outer_type))
kono
parents:
diff changeset
154 && tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
kono
parents:
diff changeset
155 && tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
kono
parents:
diff changeset
156 {
kono
parents:
diff changeset
157 bool der = maybe_derived_type; /* clear_outer_type will reset it. */
kono
parents:
diff changeset
158 bool dyn = dynamic;
kono
parents:
diff changeset
159 clear_outer_type (otr_type);
kono
parents:
diff changeset
160 type = otr_type;
kono
parents:
diff changeset
161 cur_offset = 0;
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 /* If derived type is not allowed, we know that the context is invalid.
kono
parents:
diff changeset
164 For dynamic types, we really do not have information about
kono
parents:
diff changeset
165 size of the memory location. It is possible that completely
kono
parents:
diff changeset
166 different type is stored after outer_type. */
kono
parents:
diff changeset
167 if (!der && !dyn)
kono
parents:
diff changeset
168 {
kono
parents:
diff changeset
169 clear_speculation ();
kono
parents:
diff changeset
170 invalid = true;
kono
parents:
diff changeset
171 return false;
kono
parents:
diff changeset
172 }
kono
parents:
diff changeset
173 }
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 if (otr_type && TYPE_SIZE (otr_type)
kono
parents:
diff changeset
176 && tree_fits_shwi_p (TYPE_SIZE (otr_type)))
kono
parents:
diff changeset
177 otr_type_size = tree_to_uhwi (TYPE_SIZE (otr_type));
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 if (!type || offset < 0)
kono
parents:
diff changeset
180 goto no_useful_type_info;
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 /* Find the sub-object the constant actually refers to and mark whether it is
kono
parents:
diff changeset
183 an artificial one (as opposed to a user-defined one).
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 This loop is performed twice; first time for outer_type and second time
kono
parents:
diff changeset
186 for speculative_outer_type. The second run has SPECULATIVE set. */
kono
parents:
diff changeset
187 while (true)
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 unsigned HOST_WIDE_INT pos, size;
kono
parents:
diff changeset
190 tree fld;
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 /* If we do not know size of TYPE, we need to be more conservative
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
193 about accepting cases where we cannot find EXPECTED_TYPE.
111
kono
parents:
diff changeset
194 Generally the types that do matter here are of constant size.
kono
parents:
diff changeset
195 Size_unknown case should be very rare. */
kono
parents:
diff changeset
196 if (TYPE_SIZE (type)
kono
parents:
diff changeset
197 && tree_fits_shwi_p (TYPE_SIZE (type))
kono
parents:
diff changeset
198 && tree_to_shwi (TYPE_SIZE (type)) >= 0)
kono
parents:
diff changeset
199 size_unknown = false;
kono
parents:
diff changeset
200 else
kono
parents:
diff changeset
201 size_unknown = true;
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 /* On a match, just return what we found. */
kono
parents:
diff changeset
204 if ((otr_type
kono
parents:
diff changeset
205 && types_odr_comparable (type, otr_type)
kono
parents:
diff changeset
206 && types_same_for_odr (type, otr_type))
kono
parents:
diff changeset
207 || (!otr_type
kono
parents:
diff changeset
208 && TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
209 && TYPE_BINFO (type)
kono
parents:
diff changeset
210 && polymorphic_type_binfo_p (TYPE_BINFO (type))))
kono
parents:
diff changeset
211 {
kono
parents:
diff changeset
212 if (speculative)
kono
parents:
diff changeset
213 {
kono
parents:
diff changeset
214 /* If we did not match the offset, just give up on speculation. */
kono
parents:
diff changeset
215 if (cur_offset != 0
kono
parents:
diff changeset
216 /* Also check if speculation did not end up being same as
kono
parents:
diff changeset
217 non-speculation. */
kono
parents:
diff changeset
218 || (types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
219 outer_type)
kono
parents:
diff changeset
220 && (maybe_derived_type
kono
parents:
diff changeset
221 == speculative_maybe_derived_type)))
kono
parents:
diff changeset
222 clear_speculation ();
kono
parents:
diff changeset
223 return true;
kono
parents:
diff changeset
224 }
kono
parents:
diff changeset
225 else
kono
parents:
diff changeset
226 {
kono
parents:
diff changeset
227 /* If type is known to be final, do not worry about derived
kono
parents:
diff changeset
228 types. Testing it here may help us to avoid speculation. */
kono
parents:
diff changeset
229 if (otr_type && TREE_CODE (outer_type) == RECORD_TYPE
kono
parents:
diff changeset
230 && (!in_lto_p || odr_type_p (outer_type))
kono
parents:
diff changeset
231 && type_with_linkage_p (outer_type)
kono
parents:
diff changeset
232 && type_known_to_have_no_derivations_p (outer_type))
kono
parents:
diff changeset
233 maybe_derived_type = false;
kono
parents:
diff changeset
234
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
235 /* Type cannot contain itself on an non-zero offset. In that case
111
kono
parents:
diff changeset
236 just give up. Still accept the case where size is now known.
kono
parents:
diff changeset
237 Either the second copy may appear past the end of type or within
kono
parents:
diff changeset
238 the non-POD buffer located inside the variably sized type
kono
parents:
diff changeset
239 itself. */
kono
parents:
diff changeset
240 if (cur_offset != 0)
kono
parents:
diff changeset
241 goto no_useful_type_info;
kono
parents:
diff changeset
242 /* If we determined type precisely or we have no clue on
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
243 speculation, we are done. */
111
kono
parents:
diff changeset
244 if (!maybe_derived_type || !speculative_outer_type
kono
parents:
diff changeset
245 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
246 speculative_offset,
kono
parents:
diff changeset
247 speculative_maybe_derived_type,
kono
parents:
diff changeset
248 otr_type))
kono
parents:
diff changeset
249 {
kono
parents:
diff changeset
250 clear_speculation ();
kono
parents:
diff changeset
251 return true;
kono
parents:
diff changeset
252 }
kono
parents:
diff changeset
253 /* Otherwise look into speculation now. */
kono
parents:
diff changeset
254 else
kono
parents:
diff changeset
255 {
kono
parents:
diff changeset
256 speculative = true;
kono
parents:
diff changeset
257 type = speculative_outer_type;
kono
parents:
diff changeset
258 cur_offset = speculative_offset;
kono
parents:
diff changeset
259 continue;
kono
parents:
diff changeset
260 }
kono
parents:
diff changeset
261 }
kono
parents:
diff changeset
262 }
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 /* Walk fields and find corresponding on at OFFSET. */
kono
parents:
diff changeset
265 if (TREE_CODE (type) == RECORD_TYPE)
kono
parents:
diff changeset
266 {
kono
parents:
diff changeset
267 for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
kono
parents:
diff changeset
268 {
kono
parents:
diff changeset
269 if (TREE_CODE (fld) != FIELD_DECL
kono
parents:
diff changeset
270 || TREE_TYPE (fld) == error_mark_node)
kono
parents:
diff changeset
271 continue;
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 pos = int_bit_position (fld);
kono
parents:
diff changeset
274 if (pos > (unsigned HOST_WIDE_INT)cur_offset)
kono
parents:
diff changeset
275 continue;
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 /* Do not consider vptr itself. Not even for placement new. */
kono
parents:
diff changeset
278 if (!pos && DECL_ARTIFICIAL (fld)
kono
parents:
diff changeset
279 && POINTER_TYPE_P (TREE_TYPE (fld))
kono
parents:
diff changeset
280 && TYPE_BINFO (type)
kono
parents:
diff changeset
281 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
282 continue;
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 if (!DECL_SIZE (fld) || !tree_fits_uhwi_p (DECL_SIZE (fld)))
kono
parents:
diff changeset
285 goto no_useful_type_info;
kono
parents:
diff changeset
286 size = tree_to_uhwi (DECL_SIZE (fld));
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 /* We can always skip types smaller than pointer size:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
289 those cannot contain a virtual table pointer.
111
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 Disqualifying fields that are too small to fit OTR_TYPE
kono
parents:
diff changeset
292 saves work needed to walk them for no benefit.
kono
parents:
diff changeset
293 Because of the way the bases are packed into a class, the
kono
parents:
diff changeset
294 field's size may be smaller than type size, so it needs
kono
parents:
diff changeset
295 to be done with a care. */
kono
parents:
diff changeset
296
kono
parents:
diff changeset
297 if (pos <= (unsigned HOST_WIDE_INT)cur_offset
kono
parents:
diff changeset
298 && (pos + size) >= (unsigned HOST_WIDE_INT)cur_offset
kono
parents:
diff changeset
299 + POINTER_SIZE
kono
parents:
diff changeset
300 && (!otr_type
kono
parents:
diff changeset
301 || !TYPE_SIZE (TREE_TYPE (fld))
kono
parents:
diff changeset
302 || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld)))
kono
parents:
diff changeset
303 || (pos + tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld))))
kono
parents:
diff changeset
304 >= cur_offset + otr_type_size))
kono
parents:
diff changeset
305 break;
kono
parents:
diff changeset
306 }
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 if (!fld)
kono
parents:
diff changeset
309 goto no_useful_type_info;
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
kono
parents:
diff changeset
312 cur_offset -= pos;
kono
parents:
diff changeset
313 /* DECL_ARTIFICIAL represents a basetype. */
kono
parents:
diff changeset
314 if (!DECL_ARTIFICIAL (fld))
kono
parents:
diff changeset
315 {
kono
parents:
diff changeset
316 if (!speculative)
kono
parents:
diff changeset
317 {
kono
parents:
diff changeset
318 outer_type = type;
kono
parents:
diff changeset
319 offset = cur_offset;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
320 /* As soon as we see an field containing the type,
111
kono
parents:
diff changeset
321 we know we are not looking for derivations. */
kono
parents:
diff changeset
322 maybe_derived_type = false;
kono
parents:
diff changeset
323 }
kono
parents:
diff changeset
324 else
kono
parents:
diff changeset
325 {
kono
parents:
diff changeset
326 speculative_outer_type = type;
kono
parents:
diff changeset
327 speculative_offset = cur_offset;
kono
parents:
diff changeset
328 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
329 }
kono
parents:
diff changeset
330 }
kono
parents:
diff changeset
331 else if (!consider_bases)
kono
parents:
diff changeset
332 goto no_useful_type_info;
kono
parents:
diff changeset
333 }
kono
parents:
diff changeset
334 else if (TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
335 {
kono
parents:
diff changeset
336 tree subtype = TYPE_MAIN_VARIANT (TREE_TYPE (type));
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 /* Give up if we don't know array field size.
kono
parents:
diff changeset
339 Also give up on non-polymorphic types as they are used
kono
parents:
diff changeset
340 as buffers for placement new. */
kono
parents:
diff changeset
341 if (!TYPE_SIZE (subtype)
kono
parents:
diff changeset
342 || !tree_fits_shwi_p (TYPE_SIZE (subtype))
kono
parents:
diff changeset
343 || tree_to_shwi (TYPE_SIZE (subtype)) <= 0
kono
parents:
diff changeset
344 || !contains_polymorphic_type_p (subtype))
kono
parents:
diff changeset
345 goto no_useful_type_info;
kono
parents:
diff changeset
346
kono
parents:
diff changeset
347 HOST_WIDE_INT new_offset = cur_offset % tree_to_shwi (TYPE_SIZE (subtype));
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 /* We may see buffer for placement new. In this case the expected type
kono
parents:
diff changeset
350 can be bigger than the subtype. */
kono
parents:
diff changeset
351 if (TYPE_SIZE (subtype)
kono
parents:
diff changeset
352 && (cur_offset + otr_type_size
kono
parents:
diff changeset
353 > tree_to_uhwi (TYPE_SIZE (subtype))))
kono
parents:
diff changeset
354 goto no_useful_type_info;
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 cur_offset = new_offset;
kono
parents:
diff changeset
357 type = TYPE_MAIN_VARIANT (subtype);
kono
parents:
diff changeset
358 if (!speculative)
kono
parents:
diff changeset
359 {
kono
parents:
diff changeset
360 outer_type = type;
kono
parents:
diff changeset
361 offset = cur_offset;
kono
parents:
diff changeset
362 maybe_derived_type = false;
kono
parents:
diff changeset
363 }
kono
parents:
diff changeset
364 else
kono
parents:
diff changeset
365 {
kono
parents:
diff changeset
366 speculative_outer_type = type;
kono
parents:
diff changeset
367 speculative_offset = cur_offset;
kono
parents:
diff changeset
368 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
369 }
kono
parents:
diff changeset
370 }
kono
parents:
diff changeset
371 /* Give up on anything else. */
kono
parents:
diff changeset
372 else
kono
parents:
diff changeset
373 {
kono
parents:
diff changeset
374 no_useful_type_info:
kono
parents:
diff changeset
375 if (maybe_derived_type && !speculative
kono
parents:
diff changeset
376 && TREE_CODE (outer_type) == RECORD_TYPE
kono
parents:
diff changeset
377 && TREE_CODE (otr_type) == RECORD_TYPE
kono
parents:
diff changeset
378 && TYPE_BINFO (otr_type)
kono
parents:
diff changeset
379 && !offset
kono
parents:
diff changeset
380 && get_binfo_at_offset (TYPE_BINFO (otr_type), 0, outer_type))
kono
parents:
diff changeset
381 {
kono
parents:
diff changeset
382 clear_outer_type (otr_type);
kono
parents:
diff changeset
383 if (!speculative_outer_type
kono
parents:
diff changeset
384 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
385 speculative_offset,
kono
parents:
diff changeset
386 speculative_maybe_derived_type,
kono
parents:
diff changeset
387 otr_type))
kono
parents:
diff changeset
388 clear_speculation ();
kono
parents:
diff changeset
389 if (speculative_outer_type)
kono
parents:
diff changeset
390 {
kono
parents:
diff changeset
391 speculative = true;
kono
parents:
diff changeset
392 type = speculative_outer_type;
kono
parents:
diff changeset
393 cur_offset = speculative_offset;
kono
parents:
diff changeset
394 }
kono
parents:
diff changeset
395 else
kono
parents:
diff changeset
396 return true;
kono
parents:
diff changeset
397 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
398 /* We found no way to embed EXPECTED_TYPE in TYPE.
111
kono
parents:
diff changeset
399 We still permit two special cases - placement new and
kono
parents:
diff changeset
400 the case of variadic types containing themselves. */
kono
parents:
diff changeset
401 if (!speculative
kono
parents:
diff changeset
402 && consider_placement_new
kono
parents:
diff changeset
403 && (size_unknown || !type || maybe_derived_type
kono
parents:
diff changeset
404 || possible_placement_new (type, otr_type, cur_offset)))
kono
parents:
diff changeset
405 {
kono
parents:
diff changeset
406 /* In these weird cases we want to accept the context.
kono
parents:
diff changeset
407 In non-speculative run we have no useful outer_type info
kono
parents:
diff changeset
408 (TODO: we may eventually want to record upper bound on the
kono
parents:
diff changeset
409 type size that can be used to prune the walk),
kono
parents:
diff changeset
410 but we still want to consider speculation that may
kono
parents:
diff changeset
411 give useful info. */
kono
parents:
diff changeset
412 if (!speculative)
kono
parents:
diff changeset
413 {
kono
parents:
diff changeset
414 clear_outer_type (otr_type);
kono
parents:
diff changeset
415 if (!speculative_outer_type
kono
parents:
diff changeset
416 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
417 speculative_offset,
kono
parents:
diff changeset
418 speculative_maybe_derived_type,
kono
parents:
diff changeset
419 otr_type))
kono
parents:
diff changeset
420 clear_speculation ();
kono
parents:
diff changeset
421 if (speculative_outer_type)
kono
parents:
diff changeset
422 {
kono
parents:
diff changeset
423 speculative = true;
kono
parents:
diff changeset
424 type = speculative_outer_type;
kono
parents:
diff changeset
425 cur_offset = speculative_offset;
kono
parents:
diff changeset
426 }
kono
parents:
diff changeset
427 else
kono
parents:
diff changeset
428 return true;
kono
parents:
diff changeset
429 }
kono
parents:
diff changeset
430 else
kono
parents:
diff changeset
431 {
kono
parents:
diff changeset
432 clear_speculation ();
kono
parents:
diff changeset
433 return true;
kono
parents:
diff changeset
434 }
kono
parents:
diff changeset
435 }
kono
parents:
diff changeset
436 else
kono
parents:
diff changeset
437 {
kono
parents:
diff changeset
438 clear_speculation ();
kono
parents:
diff changeset
439 if (speculative)
kono
parents:
diff changeset
440 return true;
kono
parents:
diff changeset
441 clear_outer_type (otr_type);
kono
parents:
diff changeset
442 invalid = true;
kono
parents:
diff changeset
443 return false;
kono
parents:
diff changeset
444 }
kono
parents:
diff changeset
445 }
kono
parents:
diff changeset
446 }
kono
parents:
diff changeset
447 }
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 /* Return true if OUTER_TYPE contains OTR_TYPE at OFFSET.
kono
parents:
diff changeset
450 CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can
kono
parents:
diff changeset
451 be built within OUTER_TYPE by means of placement new. CONSIDER_BASES makes
kono
parents:
diff changeset
452 function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or as
kono
parents:
diff changeset
453 base of one of fields of OUTER_TYPE. */
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 static bool
kono
parents:
diff changeset
456 contains_type_p (tree outer_type, HOST_WIDE_INT offset,
kono
parents:
diff changeset
457 tree otr_type,
kono
parents:
diff changeset
458 bool consider_placement_new,
kono
parents:
diff changeset
459 bool consider_bases)
kono
parents:
diff changeset
460 {
kono
parents:
diff changeset
461 ipa_polymorphic_call_context context;
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 /* Check that type is within range. */
kono
parents:
diff changeset
464 if (offset < 0)
kono
parents:
diff changeset
465 return false;
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 /* PR ipa/71207
kono
parents:
diff changeset
468 As OUTER_TYPE can be a type which has a diamond virtual inheritance,
kono
parents:
diff changeset
469 it's not necessary that INNER_TYPE will fit within OUTER_TYPE with
kono
parents:
diff changeset
470 a given offset. It can happen that INNER_TYPE also contains a base object,
kono
parents:
diff changeset
471 however it would point to the same instance in the OUTER_TYPE. */
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 context.offset = offset;
kono
parents:
diff changeset
474 context.outer_type = TYPE_MAIN_VARIANT (outer_type);
kono
parents:
diff changeset
475 context.maybe_derived_type = false;
kono
parents:
diff changeset
476 context.dynamic = false;
kono
parents:
diff changeset
477 return context.restrict_to_inner_class (otr_type, consider_placement_new,
kono
parents:
diff changeset
478 consider_bases);
kono
parents:
diff changeset
479 }
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 /* Return a FUNCTION_DECL if FN represent a constructor or destructor.
kono
parents:
diff changeset
483 If CHECK_CLONES is true, also check for clones of ctor/dtors. */
kono
parents:
diff changeset
484
kono
parents:
diff changeset
485 tree
kono
parents:
diff changeset
486 polymorphic_ctor_dtor_p (tree fn, bool check_clones)
kono
parents:
diff changeset
487 {
kono
parents:
diff changeset
488 if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
kono
parents:
diff changeset
489 || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
kono
parents:
diff changeset
490 {
kono
parents:
diff changeset
491 if (!check_clones)
kono
parents:
diff changeset
492 return NULL_TREE;
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 /* Watch for clones where we constant propagated the first
kono
parents:
diff changeset
495 argument (pointer to the instance). */
kono
parents:
diff changeset
496 fn = DECL_ABSTRACT_ORIGIN (fn);
kono
parents:
diff changeset
497 if (!fn
kono
parents:
diff changeset
498 || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
kono
parents:
diff changeset
499 || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn)))
kono
parents:
diff changeset
500 return NULL_TREE;
kono
parents:
diff changeset
501 }
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST))
kono
parents:
diff changeset
504 return NULL_TREE;
kono
parents:
diff changeset
505
kono
parents:
diff changeset
506 return fn;
kono
parents:
diff changeset
507 }
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 /* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
kono
parents:
diff changeset
510 If CHECK_CLONES is true, also check for clones of ctor/dtors. */
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 tree
kono
parents:
diff changeset
513 inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones)
kono
parents:
diff changeset
514 {
kono
parents:
diff changeset
515 tree fn = block_ultimate_origin (block);
kono
parents:
diff changeset
516 if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
kono
parents:
diff changeset
517 return NULL_TREE;
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 return polymorphic_ctor_dtor_p (fn, check_clones);
kono
parents:
diff changeset
520 }
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 /* We know that the instance is stored in variable or parameter
kono
parents:
diff changeset
524 (not dynamically allocated) and we want to disprove the fact
kono
parents:
diff changeset
525 that it may be in construction at invocation of CALL.
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 BASE represents memory location where instance is stored.
kono
parents:
diff changeset
528 If BASE is NULL, it is assumed to be global memory.
kono
parents:
diff changeset
529 OUTER_TYPE is known type of the instance or NULL if not
kono
parents:
diff changeset
530 known.
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532 For the variable to be in construction we actually need to
kono
parents:
diff changeset
533 be in constructor of corresponding global variable or
kono
parents:
diff changeset
534 the inline stack of CALL must contain the constructor.
kono
parents:
diff changeset
535 Check this condition. This check works safely only before
kono
parents:
diff changeset
536 IPA passes, because inline stacks may become out of date
kono
parents:
diff changeset
537 later. */
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 bool
kono
parents:
diff changeset
540 decl_maybe_in_construction_p (tree base, tree outer_type,
kono
parents:
diff changeset
541 gimple *call, tree function)
kono
parents:
diff changeset
542 {
kono
parents:
diff changeset
543 if (outer_type)
kono
parents:
diff changeset
544 outer_type = TYPE_MAIN_VARIANT (outer_type);
kono
parents:
diff changeset
545 gcc_assert (!base || DECL_P (base));
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 /* After inlining the code unification optimizations may invalidate
kono
parents:
diff changeset
548 inline stacks. Also we need to give up on global variables after
kono
parents:
diff changeset
549 IPA, because addresses of these may have been propagated to their
kono
parents:
diff changeset
550 constructors. */
kono
parents:
diff changeset
551 if (DECL_STRUCT_FUNCTION (function)->after_inlining)
kono
parents:
diff changeset
552 return true;
kono
parents:
diff changeset
553
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
554 /* Pure functions cannot do any changes on the dynamic type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
555 that require writing to memory. */
111
kono
parents:
diff changeset
556 if ((!base || !auto_var_in_fn_p (base, function))
kono
parents:
diff changeset
557 && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
kono
parents:
diff changeset
558 return false;
kono
parents:
diff changeset
559
kono
parents:
diff changeset
560 bool check_clones = !base || is_global_var (base);
kono
parents:
diff changeset
561 for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK;
kono
parents:
diff changeset
562 block = BLOCK_SUPERCONTEXT (block))
kono
parents:
diff changeset
563 if (tree fn = inlined_polymorphic_ctor_dtor_block_p (block, check_clones))
kono
parents:
diff changeset
564 {
kono
parents:
diff changeset
565 tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 if (!outer_type || !types_odr_comparable (type, outer_type))
kono
parents:
diff changeset
568 {
kono
parents:
diff changeset
569 if (TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
570 && TYPE_BINFO (type)
kono
parents:
diff changeset
571 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
572 return true;
kono
parents:
diff changeset
573 }
kono
parents:
diff changeset
574 else if (types_same_for_odr (type, outer_type))
kono
parents:
diff changeset
575 return true;
kono
parents:
diff changeset
576 }
kono
parents:
diff changeset
577
kono
parents:
diff changeset
578 if (!base || (VAR_P (base) && is_global_var (base)))
kono
parents:
diff changeset
579 {
kono
parents:
diff changeset
580 if (TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
kono
parents:
diff changeset
581 || (!DECL_CXX_CONSTRUCTOR_P (function)
kono
parents:
diff changeset
582 && !DECL_CXX_DESTRUCTOR_P (function)))
kono
parents:
diff changeset
583 {
kono
parents:
diff changeset
584 if (!DECL_ABSTRACT_ORIGIN (function))
kono
parents:
diff changeset
585 return false;
kono
parents:
diff changeset
586 /* Watch for clones where we constant propagated the first
kono
parents:
diff changeset
587 argument (pointer to the instance). */
kono
parents:
diff changeset
588 function = DECL_ABSTRACT_ORIGIN (function);
kono
parents:
diff changeset
589 if (!function
kono
parents:
diff changeset
590 || TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
kono
parents:
diff changeset
591 || (!DECL_CXX_CONSTRUCTOR_P (function)
kono
parents:
diff changeset
592 && !DECL_CXX_DESTRUCTOR_P (function)))
kono
parents:
diff changeset
593 return false;
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595 tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (function));
kono
parents:
diff changeset
596 if (!outer_type || !types_odr_comparable (type, outer_type))
kono
parents:
diff changeset
597 {
kono
parents:
diff changeset
598 if (TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
599 && TYPE_BINFO (type)
kono
parents:
diff changeset
600 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
601 return true;
kono
parents:
diff changeset
602 }
kono
parents:
diff changeset
603 else if (types_same_for_odr (type, outer_type))
kono
parents:
diff changeset
604 return true;
kono
parents:
diff changeset
605 }
kono
parents:
diff changeset
606 return false;
kono
parents:
diff changeset
607 }
kono
parents:
diff changeset
608
kono
parents:
diff changeset
609 /* Dump human readable context to F. If NEWLINE is true, it will be terminated
kono
parents:
diff changeset
610 by a newline. */
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 void
kono
parents:
diff changeset
613 ipa_polymorphic_call_context::dump (FILE *f, bool newline) const
kono
parents:
diff changeset
614 {
kono
parents:
diff changeset
615 fprintf (f, " ");
kono
parents:
diff changeset
616 if (invalid)
kono
parents:
diff changeset
617 fprintf (f, "Call is known to be undefined");
kono
parents:
diff changeset
618 else
kono
parents:
diff changeset
619 {
kono
parents:
diff changeset
620 if (useless_p ())
kono
parents:
diff changeset
621 fprintf (f, "nothing known");
kono
parents:
diff changeset
622 if (outer_type || offset)
kono
parents:
diff changeset
623 {
kono
parents:
diff changeset
624 fprintf (f, "Outer type%s:", dynamic ? " (dynamic)":"");
kono
parents:
diff changeset
625 print_generic_expr (f, outer_type, TDF_SLIM);
kono
parents:
diff changeset
626 if (maybe_derived_type)
kono
parents:
diff changeset
627 fprintf (f, " (or a derived type)");
kono
parents:
diff changeset
628 if (maybe_in_construction)
kono
parents:
diff changeset
629 fprintf (f, " (maybe in construction)");
kono
parents:
diff changeset
630 fprintf (f, " offset " HOST_WIDE_INT_PRINT_DEC,
kono
parents:
diff changeset
631 offset);
kono
parents:
diff changeset
632 }
kono
parents:
diff changeset
633 if (speculative_outer_type)
kono
parents:
diff changeset
634 {
kono
parents:
diff changeset
635 if (outer_type || offset)
kono
parents:
diff changeset
636 fprintf (f, " ");
kono
parents:
diff changeset
637 fprintf (f, "Speculative outer type:");
kono
parents:
diff changeset
638 print_generic_expr (f, speculative_outer_type, TDF_SLIM);
kono
parents:
diff changeset
639 if (speculative_maybe_derived_type)
kono
parents:
diff changeset
640 fprintf (f, " (or a derived type)");
kono
parents:
diff changeset
641 fprintf (f, " at offset " HOST_WIDE_INT_PRINT_DEC,
kono
parents:
diff changeset
642 speculative_offset);
kono
parents:
diff changeset
643 }
kono
parents:
diff changeset
644 }
kono
parents:
diff changeset
645 if (newline)
kono
parents:
diff changeset
646 fprintf(f, "\n");
kono
parents:
diff changeset
647 }
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 /* Print context to stderr. */
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 void
kono
parents:
diff changeset
652 ipa_polymorphic_call_context::debug () const
kono
parents:
diff changeset
653 {
kono
parents:
diff changeset
654 dump (stderr);
kono
parents:
diff changeset
655 }
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 /* Stream out the context to OB. */
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 void
kono
parents:
diff changeset
660 ipa_polymorphic_call_context::stream_out (struct output_block *ob) const
kono
parents:
diff changeset
661 {
kono
parents:
diff changeset
662 struct bitpack_d bp = bitpack_create (ob->main_stream);
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 bp_pack_value (&bp, invalid, 1);
kono
parents:
diff changeset
665 bp_pack_value (&bp, maybe_in_construction, 1);
kono
parents:
diff changeset
666 bp_pack_value (&bp, maybe_derived_type, 1);
kono
parents:
diff changeset
667 bp_pack_value (&bp, speculative_maybe_derived_type, 1);
kono
parents:
diff changeset
668 bp_pack_value (&bp, dynamic, 1);
kono
parents:
diff changeset
669 bp_pack_value (&bp, outer_type != NULL, 1);
kono
parents:
diff changeset
670 bp_pack_value (&bp, offset != 0, 1);
kono
parents:
diff changeset
671 bp_pack_value (&bp, speculative_outer_type != NULL, 1);
kono
parents:
diff changeset
672 streamer_write_bitpack (&bp);
kono
parents:
diff changeset
673
kono
parents:
diff changeset
674 if (outer_type != NULL)
kono
parents:
diff changeset
675 stream_write_tree (ob, outer_type, true);
kono
parents:
diff changeset
676 if (offset)
kono
parents:
diff changeset
677 streamer_write_hwi (ob, offset);
kono
parents:
diff changeset
678 if (speculative_outer_type != NULL)
kono
parents:
diff changeset
679 {
kono
parents:
diff changeset
680 stream_write_tree (ob, speculative_outer_type, true);
kono
parents:
diff changeset
681 streamer_write_hwi (ob, speculative_offset);
kono
parents:
diff changeset
682 }
kono
parents:
diff changeset
683 else
kono
parents:
diff changeset
684 gcc_assert (!speculative_offset);
kono
parents:
diff changeset
685 }
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 /* Stream in the context from IB and DATA_IN. */
kono
parents:
diff changeset
688
kono
parents:
diff changeset
689 void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
690 ipa_polymorphic_call_context::stream_in (class lto_input_block *ib,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
691 class data_in *data_in)
111
kono
parents:
diff changeset
692 {
kono
parents:
diff changeset
693 struct bitpack_d bp = streamer_read_bitpack (ib);
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 invalid = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
696 maybe_in_construction = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
697 maybe_derived_type = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
698 speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
699 dynamic = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
700 bool outer_type_p = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
701 bool offset_p = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
702 bool speculative_outer_type_p = bp_unpack_value (&bp, 1);
kono
parents:
diff changeset
703
kono
parents:
diff changeset
704 if (outer_type_p)
kono
parents:
diff changeset
705 outer_type = stream_read_tree (ib, data_in);
kono
parents:
diff changeset
706 else
kono
parents:
diff changeset
707 outer_type = NULL;
kono
parents:
diff changeset
708 if (offset_p)
kono
parents:
diff changeset
709 offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
kono
parents:
diff changeset
710 else
kono
parents:
diff changeset
711 offset = 0;
kono
parents:
diff changeset
712 if (speculative_outer_type_p)
kono
parents:
diff changeset
713 {
kono
parents:
diff changeset
714 speculative_outer_type = stream_read_tree (ib, data_in);
kono
parents:
diff changeset
715 speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
kono
parents:
diff changeset
716 }
kono
parents:
diff changeset
717 else
kono
parents:
diff changeset
718 {
kono
parents:
diff changeset
719 speculative_outer_type = NULL;
kono
parents:
diff changeset
720 speculative_offset = 0;
kono
parents:
diff changeset
721 }
kono
parents:
diff changeset
722 }
kono
parents:
diff changeset
723
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
724 /* Produce polymorphic call context for call method of instance
111
kono
parents:
diff changeset
725 that is located within BASE (that is assumed to be a decl) at offset OFF. */
kono
parents:
diff changeset
726
kono
parents:
diff changeset
727 void
kono
parents:
diff changeset
728 ipa_polymorphic_call_context::set_by_decl (tree base, HOST_WIDE_INT off)
kono
parents:
diff changeset
729 {
kono
parents:
diff changeset
730 gcc_assert (DECL_P (base));
kono
parents:
diff changeset
731 clear_speculation ();
kono
parents:
diff changeset
732
kono
parents:
diff changeset
733 if (!contains_polymorphic_type_p (TREE_TYPE (base)))
kono
parents:
diff changeset
734 {
kono
parents:
diff changeset
735 clear_outer_type ();
kono
parents:
diff changeset
736 offset = off;
kono
parents:
diff changeset
737 return;
kono
parents:
diff changeset
738 }
kono
parents:
diff changeset
739 outer_type = TYPE_MAIN_VARIANT (TREE_TYPE (base));
kono
parents:
diff changeset
740 offset = off;
kono
parents:
diff changeset
741 /* Make very conservative assumption that all objects
kono
parents:
diff changeset
742 may be in construction.
kono
parents:
diff changeset
743
kono
parents:
diff changeset
744 It is up to caller to revisit this via
kono
parents:
diff changeset
745 get_dynamic_type or decl_maybe_in_construction_p. */
kono
parents:
diff changeset
746 maybe_in_construction = true;
kono
parents:
diff changeset
747 maybe_derived_type = false;
kono
parents:
diff changeset
748 dynamic = false;
kono
parents:
diff changeset
749 }
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 /* CST is an invariant (address of decl), try to get meaningful
kono
parents:
diff changeset
752 polymorphic call context for polymorphic call of method
kono
parents:
diff changeset
753 if instance of OTR_TYPE that is located at offset OFF of this invariant.
kono
parents:
diff changeset
754 Return FALSE if nothing meaningful can be found. */
kono
parents:
diff changeset
755
kono
parents:
diff changeset
756 bool
kono
parents:
diff changeset
757 ipa_polymorphic_call_context::set_by_invariant (tree cst,
kono
parents:
diff changeset
758 tree otr_type,
kono
parents:
diff changeset
759 HOST_WIDE_INT off)
kono
parents:
diff changeset
760 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
761 poly_int64 offset2, size, max_size;
111
kono
parents:
diff changeset
762 bool reverse;
kono
parents:
diff changeset
763 tree base;
kono
parents:
diff changeset
764
kono
parents:
diff changeset
765 invalid = false;
kono
parents:
diff changeset
766 off = 0;
kono
parents:
diff changeset
767 clear_outer_type (otr_type);
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 if (TREE_CODE (cst) != ADDR_EXPR)
kono
parents:
diff changeset
770 return false;
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 cst = TREE_OPERAND (cst, 0);
kono
parents:
diff changeset
773 base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
774 if (!DECL_P (base) || !known_size_p (max_size) || maybe_ne (max_size, size))
111
kono
parents:
diff changeset
775 return false;
kono
parents:
diff changeset
776
kono
parents:
diff changeset
777 /* Only type inconsistent programs can have otr_type that is
kono
parents:
diff changeset
778 not part of outer type. */
kono
parents:
diff changeset
779 if (otr_type && !contains_type_p (TREE_TYPE (base), off, otr_type))
kono
parents:
diff changeset
780 return false;
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 set_by_decl (base, off);
kono
parents:
diff changeset
783 return true;
kono
parents:
diff changeset
784 }
kono
parents:
diff changeset
785
kono
parents:
diff changeset
786 /* See if OP is SSA name initialized as a copy or by single assignment.
kono
parents:
diff changeset
787 If so, walk the SSA graph up. Because simple PHI conditional is considered
kono
parents:
diff changeset
788 copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
kono
parents:
diff changeset
789 graph. */
kono
parents:
diff changeset
790
kono
parents:
diff changeset
791 static tree
kono
parents:
diff changeset
792 walk_ssa_copies (tree op, hash_set<tree> **global_visited = NULL)
kono
parents:
diff changeset
793 {
kono
parents:
diff changeset
794 hash_set <tree> *visited = NULL;
kono
parents:
diff changeset
795 STRIP_NOPS (op);
kono
parents:
diff changeset
796 while (TREE_CODE (op) == SSA_NAME
kono
parents:
diff changeset
797 && !SSA_NAME_IS_DEFAULT_DEF (op)
kono
parents:
diff changeset
798 /* We might be called via fold_stmt during cfgcleanup where
kono
parents:
diff changeset
799 SSA form need not be up-to-date. */
kono
parents:
diff changeset
800 && !name_registered_for_update_p (op)
kono
parents:
diff changeset
801 && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
kono
parents:
diff changeset
802 || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
kono
parents:
diff changeset
803 {
kono
parents:
diff changeset
804 if (global_visited)
kono
parents:
diff changeset
805 {
kono
parents:
diff changeset
806 if (!*global_visited)
kono
parents:
diff changeset
807 *global_visited = new hash_set<tree>;
kono
parents:
diff changeset
808 if ((*global_visited)->add (op))
kono
parents:
diff changeset
809 goto done;
kono
parents:
diff changeset
810 }
kono
parents:
diff changeset
811 else
kono
parents:
diff changeset
812 {
kono
parents:
diff changeset
813 if (!visited)
kono
parents:
diff changeset
814 visited = new hash_set<tree>;
kono
parents:
diff changeset
815 if (visited->add (op))
kono
parents:
diff changeset
816 goto done;
kono
parents:
diff changeset
817 }
kono
parents:
diff changeset
818 /* Special case
kono
parents:
diff changeset
819 if (ptr == 0)
kono
parents:
diff changeset
820 ptr = 0;
kono
parents:
diff changeset
821 else
kono
parents:
diff changeset
822 ptr = ptr.foo;
kono
parents:
diff changeset
823 This pattern is implicitly produced for casts to non-primary
kono
parents:
diff changeset
824 bases. When doing context analysis, we do not really care
kono
parents:
diff changeset
825 about the case pointer is NULL, because the call will be
kono
parents:
diff changeset
826 undefined anyway. */
kono
parents:
diff changeset
827 if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
kono
parents:
diff changeset
828 {
kono
parents:
diff changeset
829 gimple *phi = SSA_NAME_DEF_STMT (op);
kono
parents:
diff changeset
830
kono
parents:
diff changeset
831 if (gimple_phi_num_args (phi) > 2)
kono
parents:
diff changeset
832 goto done;
kono
parents:
diff changeset
833 if (gimple_phi_num_args (phi) == 1)
kono
parents:
diff changeset
834 op = gimple_phi_arg_def (phi, 0);
kono
parents:
diff changeset
835 else if (integer_zerop (gimple_phi_arg_def (phi, 0)))
kono
parents:
diff changeset
836 op = gimple_phi_arg_def (phi, 1);
kono
parents:
diff changeset
837 else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
kono
parents:
diff changeset
838 op = gimple_phi_arg_def (phi, 0);
kono
parents:
diff changeset
839 else
kono
parents:
diff changeset
840 goto done;
kono
parents:
diff changeset
841 }
kono
parents:
diff changeset
842 else
kono
parents:
diff changeset
843 {
kono
parents:
diff changeset
844 if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
kono
parents:
diff changeset
845 goto done;
kono
parents:
diff changeset
846 op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
kono
parents:
diff changeset
847 }
kono
parents:
diff changeset
848 STRIP_NOPS (op);
kono
parents:
diff changeset
849 }
kono
parents:
diff changeset
850 done:
kono
parents:
diff changeset
851 if (visited)
kono
parents:
diff changeset
852 delete (visited);
kono
parents:
diff changeset
853 return op;
kono
parents:
diff changeset
854 }
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 /* Create polymorphic call context from IP invariant CST.
kono
parents:
diff changeset
857 This is typically &global_var.
kono
parents:
diff changeset
858 OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF
kono
parents:
diff changeset
859 is offset of call. */
kono
parents:
diff changeset
860
kono
parents:
diff changeset
861 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst,
kono
parents:
diff changeset
862 tree otr_type,
kono
parents:
diff changeset
863 HOST_WIDE_INT off)
kono
parents:
diff changeset
864 {
kono
parents:
diff changeset
865 clear_speculation ();
kono
parents:
diff changeset
866 set_by_invariant (cst, otr_type, off);
kono
parents:
diff changeset
867 }
kono
parents:
diff changeset
868
kono
parents:
diff changeset
869 /* Build context for pointer REF contained in FNDECL at statement STMT.
kono
parents:
diff changeset
870 if INSTANCE is non-NULL, return pointer to the object described by
kono
parents:
diff changeset
871 the context or DECL where context is contained in. */
kono
parents:
diff changeset
872
kono
parents:
diff changeset
873 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
kono
parents:
diff changeset
874 tree ref,
kono
parents:
diff changeset
875 gimple *stmt,
kono
parents:
diff changeset
876 tree *instance)
kono
parents:
diff changeset
877 {
kono
parents:
diff changeset
878 tree otr_type = NULL;
kono
parents:
diff changeset
879 tree base_pointer;
kono
parents:
diff changeset
880 hash_set <tree> *visited = NULL;
kono
parents:
diff changeset
881
kono
parents:
diff changeset
882 if (TREE_CODE (ref) == OBJ_TYPE_REF)
kono
parents:
diff changeset
883 {
kono
parents:
diff changeset
884 otr_type = obj_type_ref_class (ref);
kono
parents:
diff changeset
885 base_pointer = OBJ_TYPE_REF_OBJECT (ref);
kono
parents:
diff changeset
886 }
kono
parents:
diff changeset
887 else
kono
parents:
diff changeset
888 base_pointer = ref;
kono
parents:
diff changeset
889
kono
parents:
diff changeset
890 /* Set up basic info in case we find nothing interesting in the analysis. */
kono
parents:
diff changeset
891 clear_speculation ();
kono
parents:
diff changeset
892 clear_outer_type (otr_type);
kono
parents:
diff changeset
893 invalid = false;
kono
parents:
diff changeset
894
kono
parents:
diff changeset
895 /* Walk SSA for outer object. */
kono
parents:
diff changeset
896 while (true)
kono
parents:
diff changeset
897 {
kono
parents:
diff changeset
898 base_pointer = walk_ssa_copies (base_pointer, &visited);
kono
parents:
diff changeset
899 if (TREE_CODE (base_pointer) == ADDR_EXPR)
kono
parents:
diff changeset
900 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
901 HOST_WIDE_INT offset2, size;
111
kono
parents:
diff changeset
902 bool reverse;
kono
parents:
diff changeset
903 tree base
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
904 = get_ref_base_and_extent_hwi (TREE_OPERAND (base_pointer, 0),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
905 &offset2, &size, &reverse);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
906 if (!base)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
907 break;
111
kono
parents:
diff changeset
908
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
909 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
910 offset + offset2,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
911 true,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
912 NULL /* Do not change outer type. */);
111
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 /* If this is a varying address, punt. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
915 if (TREE_CODE (base) == MEM_REF || DECL_P (base))
111
kono
parents:
diff changeset
916 {
kono
parents:
diff changeset
917 /* We found dereference of a pointer. Type of the pointer
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
918 and MEM_REF is meaningless, but we can look further. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
919 offset_int mem_offset;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
920 if (TREE_CODE (base) == MEM_REF
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
921 && mem_ref_offset (base).is_constant (&mem_offset))
111
kono
parents:
diff changeset
922 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
923 offset_int o = mem_offset * BITS_PER_UNIT;
111
kono
parents:
diff changeset
924 o += offset;
kono
parents:
diff changeset
925 o += offset2;
kono
parents:
diff changeset
926 if (!wi::fits_shwi_p (o))
kono
parents:
diff changeset
927 break;
kono
parents:
diff changeset
928 base_pointer = TREE_OPERAND (base, 0);
kono
parents:
diff changeset
929 offset = o.to_shwi ();
kono
parents:
diff changeset
930 outer_type = NULL;
kono
parents:
diff changeset
931 }
kono
parents:
diff changeset
932 /* We found base object. In this case the outer_type
kono
parents:
diff changeset
933 is known. */
kono
parents:
diff changeset
934 else if (DECL_P (base))
kono
parents:
diff changeset
935 {
kono
parents:
diff changeset
936 if (visited)
kono
parents:
diff changeset
937 delete (visited);
kono
parents:
diff changeset
938 /* Only type inconsistent programs can have otr_type that is
kono
parents:
diff changeset
939 not part of outer type. */
kono
parents:
diff changeset
940 if (otr_type
kono
parents:
diff changeset
941 && !contains_type_p (TREE_TYPE (base),
kono
parents:
diff changeset
942 offset + offset2, otr_type))
kono
parents:
diff changeset
943 {
kono
parents:
diff changeset
944 invalid = true;
kono
parents:
diff changeset
945 if (instance)
kono
parents:
diff changeset
946 *instance = base_pointer;
kono
parents:
diff changeset
947 return;
kono
parents:
diff changeset
948 }
kono
parents:
diff changeset
949 set_by_decl (base, offset + offset2);
kono
parents:
diff changeset
950 if (outer_type && maybe_in_construction && stmt)
kono
parents:
diff changeset
951 maybe_in_construction
kono
parents:
diff changeset
952 = decl_maybe_in_construction_p (base,
kono
parents:
diff changeset
953 outer_type,
kono
parents:
diff changeset
954 stmt,
kono
parents:
diff changeset
955 fndecl);
kono
parents:
diff changeset
956 if (instance)
kono
parents:
diff changeset
957 *instance = base;
kono
parents:
diff changeset
958 return;
kono
parents:
diff changeset
959 }
kono
parents:
diff changeset
960 else
kono
parents:
diff changeset
961 break;
kono
parents:
diff changeset
962 }
kono
parents:
diff changeset
963 else
kono
parents:
diff changeset
964 break;
kono
parents:
diff changeset
965 }
kono
parents:
diff changeset
966 else if (TREE_CODE (base_pointer) == POINTER_PLUS_EXPR
kono
parents:
diff changeset
967 && TREE_CODE (TREE_OPERAND (base_pointer, 1)) == INTEGER_CST)
kono
parents:
diff changeset
968 {
kono
parents:
diff changeset
969 offset_int o
kono
parents:
diff changeset
970 = offset_int::from (wi::to_wide (TREE_OPERAND (base_pointer, 1)),
kono
parents:
diff changeset
971 SIGNED);
kono
parents:
diff changeset
972 o *= BITS_PER_UNIT;
kono
parents:
diff changeset
973 o += offset;
kono
parents:
diff changeset
974 if (!wi::fits_shwi_p (o))
kono
parents:
diff changeset
975 break;
kono
parents:
diff changeset
976 offset = o.to_shwi ();
kono
parents:
diff changeset
977 base_pointer = TREE_OPERAND (base_pointer, 0);
kono
parents:
diff changeset
978 }
kono
parents:
diff changeset
979 else
kono
parents:
diff changeset
980 break;
kono
parents:
diff changeset
981 }
kono
parents:
diff changeset
982
kono
parents:
diff changeset
983 if (visited)
kono
parents:
diff changeset
984 delete (visited);
kono
parents:
diff changeset
985
kono
parents:
diff changeset
986 /* Try to determine type of the outer object. */
kono
parents:
diff changeset
987 if (TREE_CODE (base_pointer) == SSA_NAME
kono
parents:
diff changeset
988 && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
kono
parents:
diff changeset
989 && TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL)
kono
parents:
diff changeset
990 {
kono
parents:
diff changeset
991 /* See if parameter is THIS pointer of a method. */
kono
parents:
diff changeset
992 if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE
kono
parents:
diff changeset
993 && SSA_NAME_VAR (base_pointer) == DECL_ARGUMENTS (fndecl))
kono
parents:
diff changeset
994 {
kono
parents:
diff changeset
995 outer_type
kono
parents:
diff changeset
996 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
997 cgraph_node *node = cgraph_node::get (current_function_decl);
111
kono
parents:
diff changeset
998 gcc_assert (TREE_CODE (outer_type) == RECORD_TYPE
kono
parents:
diff changeset
999 || TREE_CODE (outer_type) == UNION_TYPE);
kono
parents:
diff changeset
1000
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1001 /* Handle the case we inlined into a thunk. In this case
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1002 thunk has THIS pointer of type bar, but it really receives
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1003 address to its base type foo which sits in bar at
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1004 0-thunk.fixed_offset. It starts with code that adds
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1005 think.fixed_offset to the pointer to compensate for this.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1006
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1007 Because we walked all the way to the beginning of thunk, we now
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1008 see pointer &bar-thunk.fixed_offset and need to compensate
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1009 for it. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1010 if (node->thunk.fixed_offset)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1011 offset -= node->thunk.fixed_offset * BITS_PER_UNIT;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1012
111
kono
parents:
diff changeset
1013 /* Dynamic casting has possibly upcasted the type
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1014 in the hierarchy. In this case outer type is less
111
kono
parents:
diff changeset
1015 informative than inner type and we should forget
kono
parents:
diff changeset
1016 about it. */
kono
parents:
diff changeset
1017 if ((otr_type
kono
parents:
diff changeset
1018 && !contains_type_p (outer_type, offset,
kono
parents:
diff changeset
1019 otr_type))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1020 || !contains_polymorphic_type_p (outer_type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1021 /* If we compile thunk with virtual offset, the THIS pointer
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1022 is adjusted by unknown value. We can't thus use outer info
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1023 at all. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1024 || node->thunk.virtual_offset_p)
111
kono
parents:
diff changeset
1025 {
kono
parents:
diff changeset
1026 outer_type = NULL;
kono
parents:
diff changeset
1027 if (instance)
kono
parents:
diff changeset
1028 *instance = base_pointer;
kono
parents:
diff changeset
1029 return;
kono
parents:
diff changeset
1030 }
kono
parents:
diff changeset
1031
kono
parents:
diff changeset
1032 dynamic = true;
kono
parents:
diff changeset
1033
kono
parents:
diff changeset
1034 /* If the function is constructor or destructor, then
kono
parents:
diff changeset
1035 the type is possibly in construction, but we know
kono
parents:
diff changeset
1036 it is not derived type. */
kono
parents:
diff changeset
1037 if (DECL_CXX_CONSTRUCTOR_P (fndecl)
kono
parents:
diff changeset
1038 || DECL_CXX_DESTRUCTOR_P (fndecl))
kono
parents:
diff changeset
1039 {
kono
parents:
diff changeset
1040 maybe_in_construction = true;
kono
parents:
diff changeset
1041 maybe_derived_type = false;
kono
parents:
diff changeset
1042 }
kono
parents:
diff changeset
1043 else
kono
parents:
diff changeset
1044 {
kono
parents:
diff changeset
1045 maybe_derived_type = true;
kono
parents:
diff changeset
1046 maybe_in_construction = false;
kono
parents:
diff changeset
1047 }
kono
parents:
diff changeset
1048 if (instance)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1049 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1050 /* If method is expanded thunk, we need to apply thunk offset
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1051 to instance pointer. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1052 if (node->thunk.virtual_offset_p
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1053 || node->thunk.fixed_offset)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1054 *instance = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1055 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1056 *instance = base_pointer;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1057 }
111
kono
parents:
diff changeset
1058 return;
kono
parents:
diff changeset
1059 }
kono
parents:
diff changeset
1060 /* Non-PODs passed by value are really passed by invisible
kono
parents:
diff changeset
1061 reference. In this case we also know the type of the
kono
parents:
diff changeset
1062 object. */
kono
parents:
diff changeset
1063 if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer)))
kono
parents:
diff changeset
1064 {
kono
parents:
diff changeset
1065 outer_type
kono
parents:
diff changeset
1066 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer)));
kono
parents:
diff changeset
1067 /* Only type inconsistent programs can have otr_type that is
kono
parents:
diff changeset
1068 not part of outer type. */
kono
parents:
diff changeset
1069 if (otr_type && !contains_type_p (outer_type, offset,
kono
parents:
diff changeset
1070 otr_type))
kono
parents:
diff changeset
1071 {
kono
parents:
diff changeset
1072 invalid = true;
kono
parents:
diff changeset
1073 if (instance)
kono
parents:
diff changeset
1074 *instance = base_pointer;
kono
parents:
diff changeset
1075 return;
kono
parents:
diff changeset
1076 }
kono
parents:
diff changeset
1077 /* Non-polymorphic types have no interest for us. */
kono
parents:
diff changeset
1078 else if (!otr_type && !contains_polymorphic_type_p (outer_type))
kono
parents:
diff changeset
1079 {
kono
parents:
diff changeset
1080 outer_type = NULL;
kono
parents:
diff changeset
1081 if (instance)
kono
parents:
diff changeset
1082 *instance = base_pointer;
kono
parents:
diff changeset
1083 return;
kono
parents:
diff changeset
1084 }
kono
parents:
diff changeset
1085 maybe_derived_type = false;
kono
parents:
diff changeset
1086 maybe_in_construction = false;
kono
parents:
diff changeset
1087 if (instance)
kono
parents:
diff changeset
1088 *instance = base_pointer;
kono
parents:
diff changeset
1089 return;
kono
parents:
diff changeset
1090 }
kono
parents:
diff changeset
1091 }
kono
parents:
diff changeset
1092
kono
parents:
diff changeset
1093 tree base_type = TREE_TYPE (base_pointer);
kono
parents:
diff changeset
1094
kono
parents:
diff changeset
1095 if (TREE_CODE (base_pointer) == SSA_NAME
kono
parents:
diff changeset
1096 && SSA_NAME_IS_DEFAULT_DEF (base_pointer)
kono
parents:
diff changeset
1097 && !(TREE_CODE (SSA_NAME_VAR (base_pointer)) == PARM_DECL
kono
parents:
diff changeset
1098 || TREE_CODE (SSA_NAME_VAR (base_pointer)) == RESULT_DECL))
kono
parents:
diff changeset
1099 {
kono
parents:
diff changeset
1100 invalid = true;
kono
parents:
diff changeset
1101 if (instance)
kono
parents:
diff changeset
1102 *instance = base_pointer;
kono
parents:
diff changeset
1103 return;
kono
parents:
diff changeset
1104 }
kono
parents:
diff changeset
1105 if (TREE_CODE (base_pointer) == SSA_NAME
kono
parents:
diff changeset
1106 && SSA_NAME_DEF_STMT (base_pointer)
kono
parents:
diff changeset
1107 && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer)))
kono
parents:
diff changeset
1108 base_type = TREE_TYPE (gimple_assign_rhs1
kono
parents:
diff changeset
1109 (SSA_NAME_DEF_STMT (base_pointer)));
kono
parents:
diff changeset
1110
kono
parents:
diff changeset
1111 if (base_type && POINTER_TYPE_P (base_type))
kono
parents:
diff changeset
1112 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base_type)),
kono
parents:
diff changeset
1113 offset,
kono
parents:
diff changeset
1114 true, NULL /* Do not change type here */);
kono
parents:
diff changeset
1115 /* TODO: There are multiple ways to derive a type. For instance
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1116 if BASE_POINTER is passed to an constructor call prior our reference.
111
kono
parents:
diff changeset
1117 We do not make this type of flow sensitive analysis yet. */
kono
parents:
diff changeset
1118 if (instance)
kono
parents:
diff changeset
1119 *instance = base_pointer;
kono
parents:
diff changeset
1120 return;
kono
parents:
diff changeset
1121 }
kono
parents:
diff changeset
1122
kono
parents:
diff changeset
1123 /* Structure to be passed in between detect_type_change and
kono
parents:
diff changeset
1124 check_stmt_for_type_change. */
kono
parents:
diff changeset
1125
kono
parents:
diff changeset
1126 struct type_change_info
kono
parents:
diff changeset
1127 {
kono
parents:
diff changeset
1128 /* Offset into the object where there is the virtual method pointer we are
kono
parents:
diff changeset
1129 looking for. */
kono
parents:
diff changeset
1130 HOST_WIDE_INT offset;
kono
parents:
diff changeset
1131 /* The declaration or SSA_NAME pointer of the base that we are checking for
kono
parents:
diff changeset
1132 type change. */
kono
parents:
diff changeset
1133 tree instance;
kono
parents:
diff changeset
1134 /* The reference to virtual table pointer used. */
kono
parents:
diff changeset
1135 tree vtbl_ptr_ref;
kono
parents:
diff changeset
1136 tree otr_type;
kono
parents:
diff changeset
1137 /* If we actually can tell the type that the object has changed to, it is
kono
parents:
diff changeset
1138 stored in this field. Otherwise it remains NULL_TREE. */
kono
parents:
diff changeset
1139 tree known_current_type;
kono
parents:
diff changeset
1140 HOST_WIDE_INT known_current_offset;
kono
parents:
diff changeset
1141
kono
parents:
diff changeset
1142 /* Set to nonzero if we possibly missed some dynamic type changes and we
kono
parents:
diff changeset
1143 should consider the set to be speculative. */
kono
parents:
diff changeset
1144 unsigned speculative;
kono
parents:
diff changeset
1145
kono
parents:
diff changeset
1146 /* Set to true if dynamic type change has been detected. */
kono
parents:
diff changeset
1147 bool type_maybe_changed;
kono
parents:
diff changeset
1148 /* Set to true if multiple types have been encountered. known_current_type
kono
parents:
diff changeset
1149 must be disregarded in that case. */
kono
parents:
diff changeset
1150 bool multiple_types_encountered;
kono
parents:
diff changeset
1151 bool seen_unanalyzed_store;
kono
parents:
diff changeset
1152 };
kono
parents:
diff changeset
1153
kono
parents:
diff changeset
1154 /* Return true if STMT is not call and can modify a virtual method table pointer.
kono
parents:
diff changeset
1155 We take advantage of fact that vtable stores must appear within constructor
kono
parents:
diff changeset
1156 and destructor functions. */
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 static bool
kono
parents:
diff changeset
1159 noncall_stmt_may_be_vtbl_ptr_store (gimple *stmt)
kono
parents:
diff changeset
1160 {
kono
parents:
diff changeset
1161 if (is_gimple_assign (stmt))
kono
parents:
diff changeset
1162 {
kono
parents:
diff changeset
1163 tree lhs = gimple_assign_lhs (stmt);
kono
parents:
diff changeset
1164
kono
parents:
diff changeset
1165 if (gimple_clobber_p (stmt))
kono
parents:
diff changeset
1166 return false;
kono
parents:
diff changeset
1167 if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs)))
kono
parents:
diff changeset
1168 {
kono
parents:
diff changeset
1169 if (flag_strict_aliasing
kono
parents:
diff changeset
1170 && !POINTER_TYPE_P (TREE_TYPE (lhs)))
kono
parents:
diff changeset
1171 return false;
kono
parents:
diff changeset
1172
kono
parents:
diff changeset
1173 if (TREE_CODE (lhs) == COMPONENT_REF
kono
parents:
diff changeset
1174 && !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
kono
parents:
diff changeset
1175 return false;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1176 /* In the future we might want to use get_ref_base_and_extent to find
111
kono
parents:
diff changeset
1177 if there is a field corresponding to the offset and if so, proceed
kono
parents:
diff changeset
1178 almost like if it was a component ref. */
kono
parents:
diff changeset
1179 }
kono
parents:
diff changeset
1180 }
kono
parents:
diff changeset
1181
kono
parents:
diff changeset
1182 /* Code unification may mess with inline stacks. */
kono
parents:
diff changeset
1183 if (cfun->after_inlining)
kono
parents:
diff changeset
1184 return true;
kono
parents:
diff changeset
1185
kono
parents:
diff changeset
1186 /* Walk the inline stack and watch out for ctors/dtors.
kono
parents:
diff changeset
1187 TODO: Maybe we can require the store to appear in toplevel
kono
parents:
diff changeset
1188 block of CTOR/DTOR. */
kono
parents:
diff changeset
1189 for (tree block = gimple_block (stmt); block && TREE_CODE (block) == BLOCK;
kono
parents:
diff changeset
1190 block = BLOCK_SUPERCONTEXT (block))
kono
parents:
diff changeset
1191 if (BLOCK_ABSTRACT_ORIGIN (block)
kono
parents:
diff changeset
1192 && TREE_CODE (block_ultimate_origin (block)) == FUNCTION_DECL)
kono
parents:
diff changeset
1193 return inlined_polymorphic_ctor_dtor_block_p (block, false);
kono
parents:
diff changeset
1194 return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE
kono
parents:
diff changeset
1195 && (DECL_CXX_CONSTRUCTOR_P (current_function_decl)
kono
parents:
diff changeset
1196 || DECL_CXX_DESTRUCTOR_P (current_function_decl)));
kono
parents:
diff changeset
1197 }
kono
parents:
diff changeset
1198
kono
parents:
diff changeset
1199 /* If STMT can be proved to be an assignment to the virtual method table
kono
parents:
diff changeset
1200 pointer of ANALYZED_OBJ and the type associated with the new table
kono
parents:
diff changeset
1201 identified, return the type. Otherwise return NULL_TREE if type changes
kono
parents:
diff changeset
1202 in unknown way or ERROR_MARK_NODE if type is unchanged. */
kono
parents:
diff changeset
1203
kono
parents:
diff changeset
1204 static tree
kono
parents:
diff changeset
1205 extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
kono
parents:
diff changeset
1206 HOST_WIDE_INT *type_offset)
kono
parents:
diff changeset
1207 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1208 poly_int64 offset, size, max_size;
111
kono
parents:
diff changeset
1209 tree lhs, rhs, base;
kono
parents:
diff changeset
1210 bool reverse;
kono
parents:
diff changeset
1211
kono
parents:
diff changeset
1212 if (!gimple_assign_single_p (stmt))
kono
parents:
diff changeset
1213 return NULL_TREE;
kono
parents:
diff changeset
1214
kono
parents:
diff changeset
1215 lhs = gimple_assign_lhs (stmt);
kono
parents:
diff changeset
1216 rhs = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
1217 if (TREE_CODE (lhs) != COMPONENT_REF
kono
parents:
diff changeset
1218 || !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
kono
parents:
diff changeset
1219 {
kono
parents:
diff changeset
1220 if (dump_file)
kono
parents:
diff changeset
1221 fprintf (dump_file, " LHS is not virtual table.\n");
kono
parents:
diff changeset
1222 return NULL_TREE;
kono
parents:
diff changeset
1223 }
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 if (tci->vtbl_ptr_ref && operand_equal_p (lhs, tci->vtbl_ptr_ref, 0))
kono
parents:
diff changeset
1226 ;
kono
parents:
diff changeset
1227 else
kono
parents:
diff changeset
1228 {
kono
parents:
diff changeset
1229 base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
kono
parents:
diff changeset
1230 if (DECL_P (tci->instance))
kono
parents:
diff changeset
1231 {
kono
parents:
diff changeset
1232 if (base != tci->instance)
kono
parents:
diff changeset
1233 {
kono
parents:
diff changeset
1234 if (dump_file)
kono
parents:
diff changeset
1235 {
kono
parents:
diff changeset
1236 fprintf (dump_file, " base:");
kono
parents:
diff changeset
1237 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1238 fprintf (dump_file, " does not match instance:");
kono
parents:
diff changeset
1239 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1240 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1241 }
kono
parents:
diff changeset
1242 return NULL_TREE;
kono
parents:
diff changeset
1243 }
kono
parents:
diff changeset
1244 }
kono
parents:
diff changeset
1245 else if (TREE_CODE (base) == MEM_REF)
kono
parents:
diff changeset
1246 {
kono
parents:
diff changeset
1247 if (!operand_equal_p (tci->instance, TREE_OPERAND (base, 0), 0))
kono
parents:
diff changeset
1248 {
kono
parents:
diff changeset
1249 if (dump_file)
kono
parents:
diff changeset
1250 {
kono
parents:
diff changeset
1251 fprintf (dump_file, " base mem ref:");
kono
parents:
diff changeset
1252 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1253 fprintf (dump_file, " does not match instance:");
kono
parents:
diff changeset
1254 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1255 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1256 }
kono
parents:
diff changeset
1257 return NULL_TREE;
kono
parents:
diff changeset
1258 }
kono
parents:
diff changeset
1259 if (!integer_zerop (TREE_OPERAND (base, 1)))
kono
parents:
diff changeset
1260 {
kono
parents:
diff changeset
1261 if (!tree_fits_shwi_p (TREE_OPERAND (base, 1)))
kono
parents:
diff changeset
1262 {
kono
parents:
diff changeset
1263 if (dump_file)
kono
parents:
diff changeset
1264 {
kono
parents:
diff changeset
1265 fprintf (dump_file, " base mem ref:");
kono
parents:
diff changeset
1266 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1267 fprintf (dump_file, " has non-representable offset:");
kono
parents:
diff changeset
1268 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1269 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1270 }
kono
parents:
diff changeset
1271 return NULL_TREE;
kono
parents:
diff changeset
1272 }
kono
parents:
diff changeset
1273 else
kono
parents:
diff changeset
1274 offset += tree_to_shwi (TREE_OPERAND (base, 1)) * BITS_PER_UNIT;
kono
parents:
diff changeset
1275 }
kono
parents:
diff changeset
1276 }
kono
parents:
diff changeset
1277 else if (!operand_equal_p (tci->instance, base, 0)
kono
parents:
diff changeset
1278 || tci->offset)
kono
parents:
diff changeset
1279 {
kono
parents:
diff changeset
1280 if (dump_file)
kono
parents:
diff changeset
1281 {
kono
parents:
diff changeset
1282 fprintf (dump_file, " base:");
kono
parents:
diff changeset
1283 print_generic_expr (dump_file, base, TDF_SLIM);
kono
parents:
diff changeset
1284 fprintf (dump_file, " does not match instance:");
kono
parents:
diff changeset
1285 print_generic_expr (dump_file, tci->instance, TDF_SLIM);
kono
parents:
diff changeset
1286 fprintf (dump_file, " with offset %i\n", (int)tci->offset);
kono
parents:
diff changeset
1287 }
kono
parents:
diff changeset
1288 return tci->offset > POINTER_SIZE ? error_mark_node : NULL_TREE;
kono
parents:
diff changeset
1289 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1290 if (maybe_ne (offset, tci->offset)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1291 || maybe_ne (size, POINTER_SIZE)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1292 || maybe_ne (max_size, POINTER_SIZE))
111
kono
parents:
diff changeset
1293 {
kono
parents:
diff changeset
1294 if (dump_file)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1295 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1296 fprintf (dump_file, " wrong offset ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1297 print_dec (offset, dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1298 fprintf (dump_file, "!=%i or size ", (int) tci->offset);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1299 print_dec (size, dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1300 fprintf (dump_file, "\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1301 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1302 return (known_le (offset + POINTER_SIZE, tci->offset)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1303 || (known_size_p (max_size)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1304 && known_gt (tci->offset + POINTER_SIZE,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1305 offset + max_size))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1306 ? error_mark_node : NULL);
111
kono
parents:
diff changeset
1307 }
kono
parents:
diff changeset
1308 }
kono
parents:
diff changeset
1309
kono
parents:
diff changeset
1310 tree vtable;
kono
parents:
diff changeset
1311 unsigned HOST_WIDE_INT offset2;
kono
parents:
diff changeset
1312
kono
parents:
diff changeset
1313 if (!vtable_pointer_value_to_vtable (rhs, &vtable, &offset2))
kono
parents:
diff changeset
1314 {
kono
parents:
diff changeset
1315 if (dump_file)
kono
parents:
diff changeset
1316 fprintf (dump_file, " Failed to lookup binfo\n");
kono
parents:
diff changeset
1317 return NULL;
kono
parents:
diff changeset
1318 }
kono
parents:
diff changeset
1319
kono
parents:
diff changeset
1320 tree binfo = subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)),
kono
parents:
diff changeset
1321 offset2, vtable);
kono
parents:
diff changeset
1322 if (!binfo)
kono
parents:
diff changeset
1323 {
kono
parents:
diff changeset
1324 if (dump_file)
kono
parents:
diff changeset
1325 fprintf (dump_file, " Construction vtable used\n");
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1326 /* FIXME: We should support construction contexts. */
111
kono
parents:
diff changeset
1327 return NULL;
kono
parents:
diff changeset
1328 }
kono
parents:
diff changeset
1329
kono
parents:
diff changeset
1330 *type_offset = tree_to_shwi (BINFO_OFFSET (binfo)) * BITS_PER_UNIT;
kono
parents:
diff changeset
1331 return DECL_CONTEXT (vtable);
kono
parents:
diff changeset
1332 }
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 /* Record dynamic type change of TCI to TYPE. */
kono
parents:
diff changeset
1335
kono
parents:
diff changeset
1336 static void
kono
parents:
diff changeset
1337 record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset)
kono
parents:
diff changeset
1338 {
kono
parents:
diff changeset
1339 if (dump_file)
kono
parents:
diff changeset
1340 {
kono
parents:
diff changeset
1341 if (type)
kono
parents:
diff changeset
1342 {
kono
parents:
diff changeset
1343 fprintf (dump_file, " Recording type: ");
kono
parents:
diff changeset
1344 print_generic_expr (dump_file, type, TDF_SLIM);
kono
parents:
diff changeset
1345 fprintf (dump_file, " at offset %i\n", (int)offset);
kono
parents:
diff changeset
1346 }
kono
parents:
diff changeset
1347 else
kono
parents:
diff changeset
1348 fprintf (dump_file, " Recording unknown type\n");
kono
parents:
diff changeset
1349 }
kono
parents:
diff changeset
1350
kono
parents:
diff changeset
1351 /* If we found a constructor of type that is not polymorphic or
kono
parents:
diff changeset
1352 that may contain the type in question as a field (not as base),
kono
parents:
diff changeset
1353 restrict to the inner class first to make type matching bellow
kono
parents:
diff changeset
1354 happier. */
kono
parents:
diff changeset
1355 if (type
kono
parents:
diff changeset
1356 && (offset
kono
parents:
diff changeset
1357 || (TREE_CODE (type) != RECORD_TYPE
kono
parents:
diff changeset
1358 || !TYPE_BINFO (type)
kono
parents:
diff changeset
1359 || !polymorphic_type_binfo_p (TYPE_BINFO (type)))))
kono
parents:
diff changeset
1360 {
kono
parents:
diff changeset
1361 ipa_polymorphic_call_context context;
kono
parents:
diff changeset
1362
kono
parents:
diff changeset
1363 context.offset = offset;
kono
parents:
diff changeset
1364 context.outer_type = type;
kono
parents:
diff changeset
1365 context.maybe_in_construction = false;
kono
parents:
diff changeset
1366 context.maybe_derived_type = false;
kono
parents:
diff changeset
1367 context.dynamic = true;
kono
parents:
diff changeset
1368 /* If we failed to find the inner type, we know that the call
kono
parents:
diff changeset
1369 would be undefined for type produced here. */
kono
parents:
diff changeset
1370 if (!context.restrict_to_inner_class (tci->otr_type))
kono
parents:
diff changeset
1371 {
kono
parents:
diff changeset
1372 if (dump_file)
kono
parents:
diff changeset
1373 fprintf (dump_file, " Ignoring; does not contain otr_type\n");
kono
parents:
diff changeset
1374 return;
kono
parents:
diff changeset
1375 }
kono
parents:
diff changeset
1376 /* Watch for case we reached an POD type and anticipate placement
kono
parents:
diff changeset
1377 new. */
kono
parents:
diff changeset
1378 if (!context.maybe_derived_type)
kono
parents:
diff changeset
1379 {
kono
parents:
diff changeset
1380 type = context.outer_type;
kono
parents:
diff changeset
1381 offset = context.offset;
kono
parents:
diff changeset
1382 }
kono
parents:
diff changeset
1383 }
kono
parents:
diff changeset
1384 if (tci->type_maybe_changed
kono
parents:
diff changeset
1385 && (!types_same_for_odr (type, tci->known_current_type)
kono
parents:
diff changeset
1386 || offset != tci->known_current_offset))
kono
parents:
diff changeset
1387 tci->multiple_types_encountered = true;
kono
parents:
diff changeset
1388 tci->known_current_type = TYPE_MAIN_VARIANT (type);
kono
parents:
diff changeset
1389 tci->known_current_offset = offset;
kono
parents:
diff changeset
1390 tci->type_maybe_changed = true;
kono
parents:
diff changeset
1391 }
kono
parents:
diff changeset
1392
kono
parents:
diff changeset
1393
kono
parents:
diff changeset
1394 /* The maximum number of may-defs we visit when looking for a must-def
kono
parents:
diff changeset
1395 that changes the dynamic type in check_stmt_for_type_change. Tuned
kono
parents:
diff changeset
1396 after the PR12392 testcase which unlimited spends 40% time within
kono
parents:
diff changeset
1397 these alias walks and 8% with the following limit. */
kono
parents:
diff changeset
1398
kono
parents:
diff changeset
1399 static inline bool
kono
parents:
diff changeset
1400 csftc_abort_walking_p (unsigned speculative)
kono
parents:
diff changeset
1401 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1402 unsigned max = param_max_speculative_devirt_maydefs;
111
kono
parents:
diff changeset
1403 return speculative > max ? true : false;
kono
parents:
diff changeset
1404 }
kono
parents:
diff changeset
1405
kono
parents:
diff changeset
1406 /* Callback of walk_aliased_vdefs and a helper function for
kono
parents:
diff changeset
1407 detect_type_change to check whether a particular statement may modify
kono
parents:
diff changeset
1408 the virtual table pointer, and if possible also determine the new type of
kono
parents:
diff changeset
1409 the (sub-)object. It stores its result into DATA, which points to a
kono
parents:
diff changeset
1410 type_change_info structure. */
kono
parents:
diff changeset
1411
kono
parents:
diff changeset
1412 static bool
kono
parents:
diff changeset
1413 check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
kono
parents:
diff changeset
1414 {
kono
parents:
diff changeset
1415 gimple *stmt = SSA_NAME_DEF_STMT (vdef);
kono
parents:
diff changeset
1416 struct type_change_info *tci = (struct type_change_info *) data;
kono
parents:
diff changeset
1417 tree fn;
kono
parents:
diff changeset
1418
kono
parents:
diff changeset
1419 /* If we already gave up, just terminate the rest of walk. */
kono
parents:
diff changeset
1420 if (tci->multiple_types_encountered)
kono
parents:
diff changeset
1421 return true;
kono
parents:
diff changeset
1422
kono
parents:
diff changeset
1423 if (is_gimple_call (stmt))
kono
parents:
diff changeset
1424 {
kono
parents:
diff changeset
1425 if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
kono
parents:
diff changeset
1426 return false;
kono
parents:
diff changeset
1427
kono
parents:
diff changeset
1428 /* Check for a constructor call. */
kono
parents:
diff changeset
1429 if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
kono
parents:
diff changeset
1430 && DECL_CXX_CONSTRUCTOR_P (fn)
kono
parents:
diff changeset
1431 && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
kono
parents:
diff changeset
1432 && gimple_call_num_args (stmt))
kono
parents:
diff changeset
1433 {
kono
parents:
diff changeset
1434 tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
kono
parents:
diff changeset
1435 tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1436 HOST_WIDE_INT offset = 0;
111
kono
parents:
diff changeset
1437 bool reverse;
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 if (dump_file)
kono
parents:
diff changeset
1440 {
kono
parents:
diff changeset
1441 fprintf (dump_file, " Checking constructor call: ");
kono
parents:
diff changeset
1442 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1443 }
kono
parents:
diff changeset
1444
kono
parents:
diff changeset
1445 /* See if THIS parameter seems like instance pointer. */
kono
parents:
diff changeset
1446 if (TREE_CODE (op) == ADDR_EXPR)
kono
parents:
diff changeset
1447 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1448 HOST_WIDE_INT size;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1449 op = get_ref_base_and_extent_hwi (TREE_OPERAND (op, 0),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1450 &offset, &size, &reverse);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1451 if (!op)
111
kono
parents:
diff changeset
1452 {
kono
parents:
diff changeset
1453 tci->speculative++;
kono
parents:
diff changeset
1454 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1455 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1456 if (TREE_CODE (op) == MEM_REF)
111
kono
parents:
diff changeset
1457 {
kono
parents:
diff changeset
1458 if (!tree_fits_shwi_p (TREE_OPERAND (op, 1)))
kono
parents:
diff changeset
1459 {
kono
parents:
diff changeset
1460 tci->speculative++;
kono
parents:
diff changeset
1461 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1462 }
kono
parents:
diff changeset
1463 offset += tree_to_shwi (TREE_OPERAND (op, 1))
kono
parents:
diff changeset
1464 * BITS_PER_UNIT;
kono
parents:
diff changeset
1465 op = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
1466 }
kono
parents:
diff changeset
1467 else if (DECL_P (op))
kono
parents:
diff changeset
1468 ;
kono
parents:
diff changeset
1469 else
kono
parents:
diff changeset
1470 {
kono
parents:
diff changeset
1471 tci->speculative++;
kono
parents:
diff changeset
1472 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1473 }
kono
parents:
diff changeset
1474 op = walk_ssa_copies (op);
kono
parents:
diff changeset
1475 }
kono
parents:
diff changeset
1476 if (operand_equal_p (op, tci->instance, 0)
kono
parents:
diff changeset
1477 && TYPE_SIZE (type)
kono
parents:
diff changeset
1478 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
kono
parents:
diff changeset
1479 && tree_fits_shwi_p (TYPE_SIZE (type))
kono
parents:
diff changeset
1480 && tree_to_shwi (TYPE_SIZE (type)) + offset > tci->offset
kono
parents:
diff changeset
1481 /* Some inlined constructors may look as follows:
kono
parents:
diff changeset
1482 _3 = operator new (16);
kono
parents:
diff changeset
1483 MEM[(struct &)_3] ={v} {CLOBBER};
kono
parents:
diff changeset
1484 MEM[(struct CompositeClass *)_3]._vptr.CompositeClass
kono
parents:
diff changeset
1485 = &MEM[(void *)&_ZTV14CompositeClass + 16B];
kono
parents:
diff changeset
1486 _7 = &MEM[(struct CompositeClass *)_3].object;
kono
parents:
diff changeset
1487 EmptyClass::EmptyClass (_7);
kono
parents:
diff changeset
1488
kono
parents:
diff changeset
1489 When determining dynamic type of _3 and because we stop at first
kono
parents:
diff changeset
1490 dynamic type found, we would stop on EmptyClass::EmptyClass (_7).
kono
parents:
diff changeset
1491 In this case the emptyclass is not even polymorphic and we miss
kono
parents:
diff changeset
1492 it is contained in an outer type that is polymorphic. */
kono
parents:
diff changeset
1493
kono
parents:
diff changeset
1494 && (tci->offset == offset || contains_polymorphic_type_p (type)))
kono
parents:
diff changeset
1495 {
kono
parents:
diff changeset
1496 record_known_type (tci, type, tci->offset - offset);
kono
parents:
diff changeset
1497 return true;
kono
parents:
diff changeset
1498 }
kono
parents:
diff changeset
1499 }
kono
parents:
diff changeset
1500 /* Calls may possibly change dynamic type by placement new. Assume
kono
parents:
diff changeset
1501 it will not happen, but make result speculative only. */
kono
parents:
diff changeset
1502 if (dump_file)
kono
parents:
diff changeset
1503 {
kono
parents:
diff changeset
1504 fprintf (dump_file, " Function call may change dynamic type:");
kono
parents:
diff changeset
1505 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1506 }
kono
parents:
diff changeset
1507 tci->speculative++;
kono
parents:
diff changeset
1508 return csftc_abort_walking_p (tci->speculative);
kono
parents:
diff changeset
1509 }
kono
parents:
diff changeset
1510 /* Check for inlined virtual table store. */
kono
parents:
diff changeset
1511 else if (noncall_stmt_may_be_vtbl_ptr_store (stmt))
kono
parents:
diff changeset
1512 {
kono
parents:
diff changeset
1513 tree type;
kono
parents:
diff changeset
1514 HOST_WIDE_INT offset = 0;
kono
parents:
diff changeset
1515 if (dump_file)
kono
parents:
diff changeset
1516 {
kono
parents:
diff changeset
1517 fprintf (dump_file, " Checking vtbl store: ");
kono
parents:
diff changeset
1518 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1519 }
kono
parents:
diff changeset
1520
kono
parents:
diff changeset
1521 type = extr_type_from_vtbl_ptr_store (stmt, tci, &offset);
kono
parents:
diff changeset
1522 if (type == error_mark_node)
kono
parents:
diff changeset
1523 return false;
kono
parents:
diff changeset
1524 gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
kono
parents:
diff changeset
1525 if (!type)
kono
parents:
diff changeset
1526 {
kono
parents:
diff changeset
1527 if (dump_file)
kono
parents:
diff changeset
1528 fprintf (dump_file, " Unanalyzed store may change type.\n");
kono
parents:
diff changeset
1529 tci->seen_unanalyzed_store = true;
kono
parents:
diff changeset
1530 tci->speculative++;
kono
parents:
diff changeset
1531 }
kono
parents:
diff changeset
1532 else
kono
parents:
diff changeset
1533 record_known_type (tci, type, offset);
kono
parents:
diff changeset
1534 return true;
kono
parents:
diff changeset
1535 }
kono
parents:
diff changeset
1536 else
kono
parents:
diff changeset
1537 return false;
kono
parents:
diff changeset
1538 }
kono
parents:
diff changeset
1539
kono
parents:
diff changeset
1540 /* THIS is polymorphic call context obtained from get_polymorphic_context.
kono
parents:
diff changeset
1541 OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
kono
parents:
diff changeset
1542 INSTANCE is pointer to the outer instance as returned by
kono
parents:
diff changeset
1543 get_polymorphic_context. To avoid creation of temporary expressions,
kono
parents:
diff changeset
1544 INSTANCE may also be an declaration of get_polymorphic_context found the
kono
parents:
diff changeset
1545 value to be in static storage.
kono
parents:
diff changeset
1546
kono
parents:
diff changeset
1547 If the type of instance is not fully determined
kono
parents:
diff changeset
1548 (either OUTER_TYPE is unknown or MAYBE_IN_CONSTRUCTION/INCLUDE_DERIVED_TYPES
kono
parents:
diff changeset
1549 is set), try to walk memory writes and find the actual construction of the
kono
parents:
diff changeset
1550 instance.
kono
parents:
diff changeset
1551
kono
parents:
diff changeset
1552 Return true if memory is unchanged from function entry.
kono
parents:
diff changeset
1553
kono
parents:
diff changeset
1554 We do not include this analysis in the context analysis itself, because
kono
parents:
diff changeset
1555 it needs memory SSA to be fully built and the walk may be expensive.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1556 So it is not suitable for use withing fold_stmt and similar uses.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1557
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1558 AA_WALK_BUDGET_P, if not NULL, is how statements we should allow
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1559 walk_aliased_vdefs to examine. The value should be decremented by the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1560 number of statements we examined or set to zero if exhausted. */
111
kono
parents:
diff changeset
1561
kono
parents:
diff changeset
1562 bool
kono
parents:
diff changeset
1563 ipa_polymorphic_call_context::get_dynamic_type (tree instance,
kono
parents:
diff changeset
1564 tree otr_object,
kono
parents:
diff changeset
1565 tree otr_type,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1566 gimple *call,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1567 unsigned *aa_walk_budget_p)
111
kono
parents:
diff changeset
1568 {
kono
parents:
diff changeset
1569 struct type_change_info tci;
kono
parents:
diff changeset
1570 ao_ref ao;
kono
parents:
diff changeset
1571 bool function_entry_reached = false;
kono
parents:
diff changeset
1572 tree instance_ref = NULL;
kono
parents:
diff changeset
1573 gimple *stmt = call;
kono
parents:
diff changeset
1574 /* Remember OFFSET before it is modified by restrict_to_inner_class.
kono
parents:
diff changeset
1575 This is because we do not update INSTANCE when walking inwards. */
kono
parents:
diff changeset
1576 HOST_WIDE_INT instance_offset = offset;
kono
parents:
diff changeset
1577 tree instance_outer_type = outer_type;
kono
parents:
diff changeset
1578
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1579 if (!instance)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1580 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1581
111
kono
parents:
diff changeset
1582 if (otr_type)
kono
parents:
diff changeset
1583 otr_type = TYPE_MAIN_VARIANT (otr_type);
kono
parents:
diff changeset
1584
kono
parents:
diff changeset
1585 /* Walk into inner type. This may clear maybe_derived_type and save us
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1586 from useless work. It also makes later comparisons with static type
111
kono
parents:
diff changeset
1587 easier. */
kono
parents:
diff changeset
1588 if (outer_type && otr_type)
kono
parents:
diff changeset
1589 {
kono
parents:
diff changeset
1590 if (!restrict_to_inner_class (otr_type))
kono
parents:
diff changeset
1591 return false;
kono
parents:
diff changeset
1592 }
kono
parents:
diff changeset
1593
kono
parents:
diff changeset
1594 if (!maybe_in_construction && !maybe_derived_type)
kono
parents:
diff changeset
1595 return false;
kono
parents:
diff changeset
1596
kono
parents:
diff changeset
1597 /* If we are in fact not looking at any object object or the instance is
kono
parents:
diff changeset
1598 some placement new into a random load, give up straight away. */
kono
parents:
diff changeset
1599 if (TREE_CODE (instance) == MEM_REF)
kono
parents:
diff changeset
1600 return false;
kono
parents:
diff changeset
1601
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1602 /* We need to obtain reference to virtual table pointer. It is better
111
kono
parents:
diff changeset
1603 to look it up in the code rather than build our own. This require bit
kono
parents:
diff changeset
1604 of pattern matching, but we end up verifying that what we found is
kono
parents:
diff changeset
1605 correct.
kono
parents:
diff changeset
1606
kono
parents:
diff changeset
1607 What we pattern match is:
kono
parents:
diff changeset
1608
kono
parents:
diff changeset
1609 tmp = instance->_vptr.A; // vtbl ptr load
kono
parents:
diff changeset
1610 tmp2 = tmp[otr_token]; // vtable lookup
kono
parents:
diff changeset
1611 OBJ_TYPE_REF(tmp2;instance->0) (instance);
kono
parents:
diff changeset
1612
kono
parents:
diff changeset
1613 We want to start alias oracle walk from vtbl pointer load,
kono
parents:
diff changeset
1614 but we may not be able to identify it, for example, when PRE moved the
kono
parents:
diff changeset
1615 load around. */
kono
parents:
diff changeset
1616
kono
parents:
diff changeset
1617 if (gimple_code (call) == GIMPLE_CALL)
kono
parents:
diff changeset
1618 {
kono
parents:
diff changeset
1619 tree ref = gimple_call_fn (call);
kono
parents:
diff changeset
1620 bool reverse;
kono
parents:
diff changeset
1621
kono
parents:
diff changeset
1622 if (TREE_CODE (ref) == OBJ_TYPE_REF)
kono
parents:
diff changeset
1623 {
kono
parents:
diff changeset
1624 ref = OBJ_TYPE_REF_EXPR (ref);
kono
parents:
diff changeset
1625 ref = walk_ssa_copies (ref);
kono
parents:
diff changeset
1626
kono
parents:
diff changeset
1627 /* If call target is already known, no need to do the expensive
kono
parents:
diff changeset
1628 memory walk. */
kono
parents:
diff changeset
1629 if (is_gimple_min_invariant (ref))
kono
parents:
diff changeset
1630 return false;
kono
parents:
diff changeset
1631
kono
parents:
diff changeset
1632 /* Check if definition looks like vtable lookup. */
kono
parents:
diff changeset
1633 if (TREE_CODE (ref) == SSA_NAME
kono
parents:
diff changeset
1634 && !SSA_NAME_IS_DEFAULT_DEF (ref)
kono
parents:
diff changeset
1635 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref))
kono
parents:
diff changeset
1636 && TREE_CODE (gimple_assign_rhs1
kono
parents:
diff changeset
1637 (SSA_NAME_DEF_STMT (ref))) == MEM_REF)
kono
parents:
diff changeset
1638 {
kono
parents:
diff changeset
1639 ref = get_base_address
kono
parents:
diff changeset
1640 (TREE_OPERAND (gimple_assign_rhs1
kono
parents:
diff changeset
1641 (SSA_NAME_DEF_STMT (ref)), 0));
kono
parents:
diff changeset
1642 ref = walk_ssa_copies (ref);
kono
parents:
diff changeset
1643 /* Find base address of the lookup and see if it looks like
kono
parents:
diff changeset
1644 vptr load. */
kono
parents:
diff changeset
1645 if (TREE_CODE (ref) == SSA_NAME
kono
parents:
diff changeset
1646 && !SSA_NAME_IS_DEFAULT_DEF (ref)
kono
parents:
diff changeset
1647 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
kono
parents:
diff changeset
1648 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1649 HOST_WIDE_INT offset2, size;
111
kono
parents:
diff changeset
1650 tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
kono
parents:
diff changeset
1651 tree base_ref
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1652 = get_ref_base_and_extent_hwi (ref_exp, &offset2,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1653 &size, &reverse);
111
kono
parents:
diff changeset
1654
kono
parents:
diff changeset
1655 /* Finally verify that what we found looks like read from
kono
parents:
diff changeset
1656 OTR_OBJECT or from INSTANCE with offset OFFSET. */
kono
parents:
diff changeset
1657 if (base_ref
kono
parents:
diff changeset
1658 && ((TREE_CODE (base_ref) == MEM_REF
kono
parents:
diff changeset
1659 && ((offset2 == instance_offset
kono
parents:
diff changeset
1660 && TREE_OPERAND (base_ref, 0) == instance)
kono
parents:
diff changeset
1661 || (!offset2
kono
parents:
diff changeset
1662 && TREE_OPERAND (base_ref, 0)
kono
parents:
diff changeset
1663 == otr_object)))
kono
parents:
diff changeset
1664 || (DECL_P (instance) && base_ref == instance
kono
parents:
diff changeset
1665 && offset2 == instance_offset)))
kono
parents:
diff changeset
1666 {
kono
parents:
diff changeset
1667 stmt = SSA_NAME_DEF_STMT (ref);
kono
parents:
diff changeset
1668 instance_ref = ref_exp;
kono
parents:
diff changeset
1669 }
kono
parents:
diff changeset
1670 }
kono
parents:
diff changeset
1671 }
kono
parents:
diff changeset
1672 }
kono
parents:
diff changeset
1673 }
kono
parents:
diff changeset
1674
kono
parents:
diff changeset
1675 /* If we failed to look up the reference in code, build our own. */
kono
parents:
diff changeset
1676 if (!instance_ref)
kono
parents:
diff changeset
1677 {
kono
parents:
diff changeset
1678 /* If the statement in question does not use memory, we can't tell
kono
parents:
diff changeset
1679 anything. */
kono
parents:
diff changeset
1680 if (!gimple_vuse (stmt))
kono
parents:
diff changeset
1681 return false;
kono
parents:
diff changeset
1682 ao_ref_init_from_ptr_and_size (&ao, otr_object, NULL);
kono
parents:
diff changeset
1683 }
kono
parents:
diff changeset
1684 else
kono
parents:
diff changeset
1685 /* Otherwise use the real reference. */
kono
parents:
diff changeset
1686 ao_ref_init (&ao, instance_ref);
kono
parents:
diff changeset
1687
kono
parents:
diff changeset
1688 /* We look for vtbl pointer read. */
kono
parents:
diff changeset
1689 ao.size = POINTER_SIZE;
kono
parents:
diff changeset
1690 ao.max_size = ao.size;
kono
parents:
diff changeset
1691 /* We are looking for stores to vptr pointer within the instance of
kono
parents:
diff changeset
1692 outer type.
kono
parents:
diff changeset
1693 TODO: The vptr pointer type is globally known, we probably should
kono
parents:
diff changeset
1694 keep it and do that even when otr_type is unknown. */
kono
parents:
diff changeset
1695 if (otr_type)
kono
parents:
diff changeset
1696 {
kono
parents:
diff changeset
1697 ao.base_alias_set
kono
parents:
diff changeset
1698 = get_alias_set (outer_type ? outer_type : otr_type);
kono
parents:
diff changeset
1699 ao.ref_alias_set
kono
parents:
diff changeset
1700 = get_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type))));
kono
parents:
diff changeset
1701 }
kono
parents:
diff changeset
1702
kono
parents:
diff changeset
1703 if (dump_file)
kono
parents:
diff changeset
1704 {
kono
parents:
diff changeset
1705 fprintf (dump_file, "Determining dynamic type for call: ");
kono
parents:
diff changeset
1706 print_gimple_stmt (dump_file, call, 0);
kono
parents:
diff changeset
1707 fprintf (dump_file, " Starting walk at: ");
kono
parents:
diff changeset
1708 print_gimple_stmt (dump_file, stmt, 0);
kono
parents:
diff changeset
1709 fprintf (dump_file, " instance pointer: ");
kono
parents:
diff changeset
1710 print_generic_expr (dump_file, otr_object, TDF_SLIM);
kono
parents:
diff changeset
1711 fprintf (dump_file, " Outer instance pointer: ");
kono
parents:
diff changeset
1712 print_generic_expr (dump_file, instance, TDF_SLIM);
kono
parents:
diff changeset
1713 fprintf (dump_file, " offset: %i (bits)", (int)instance_offset);
kono
parents:
diff changeset
1714 fprintf (dump_file, " vtbl reference: ");
kono
parents:
diff changeset
1715 print_generic_expr (dump_file, instance_ref, TDF_SLIM);
kono
parents:
diff changeset
1716 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1717 }
kono
parents:
diff changeset
1718
kono
parents:
diff changeset
1719 tci.offset = instance_offset;
kono
parents:
diff changeset
1720 tci.instance = instance;
kono
parents:
diff changeset
1721 tci.vtbl_ptr_ref = instance_ref;
kono
parents:
diff changeset
1722 tci.known_current_type = NULL_TREE;
kono
parents:
diff changeset
1723 tci.known_current_offset = 0;
kono
parents:
diff changeset
1724 tci.otr_type = otr_type;
kono
parents:
diff changeset
1725 tci.type_maybe_changed = false;
kono
parents:
diff changeset
1726 tci.multiple_types_encountered = false;
kono
parents:
diff changeset
1727 tci.speculative = 0;
kono
parents:
diff changeset
1728 tci.seen_unanalyzed_store = false;
kono
parents:
diff changeset
1729
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1730 unsigned aa_walk_budget = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1731 if (aa_walk_budget_p)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1732 aa_walk_budget = *aa_walk_budget_p + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1733
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1734 int walked
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1735 = walk_aliased_vdefs (&ao, gimple_vuse (stmt), check_stmt_for_type_change,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1736 &tci, NULL, &function_entry_reached, aa_walk_budget);
111
kono
parents:
diff changeset
1737
kono
parents:
diff changeset
1738 /* If we did not find any type changing statements, we may still drop
kono
parents:
diff changeset
1739 maybe_in_construction flag if the context already have outer type.
kono
parents:
diff changeset
1740
kono
parents:
diff changeset
1741 Here we make special assumptions about both constructors and
kono
parents:
diff changeset
1742 destructors which are all the functions that are allowed to alter the
kono
parents:
diff changeset
1743 VMT pointers. It assumes that destructors begin with assignment into
kono
parents:
diff changeset
1744 all VMT pointers and that constructors essentially look in the
kono
parents:
diff changeset
1745 following way:
kono
parents:
diff changeset
1746
kono
parents:
diff changeset
1747 1) The very first thing they do is that they call constructors of
kono
parents:
diff changeset
1748 ancestor sub-objects that have them.
kono
parents:
diff changeset
1749
kono
parents:
diff changeset
1750 2) Then VMT pointers of this and all its ancestors is set to new
kono
parents:
diff changeset
1751 values corresponding to the type corresponding to the constructor.
kono
parents:
diff changeset
1752
kono
parents:
diff changeset
1753 3) Only afterwards, other stuff such as constructor of member
kono
parents:
diff changeset
1754 sub-objects and the code written by the user is run. Only this may
kono
parents:
diff changeset
1755 include calling virtual functions, directly or indirectly.
kono
parents:
diff changeset
1756
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1757 4) placement new cannot be used to change type of non-POD statically
111
kono
parents:
diff changeset
1758 allocated variables.
kono
parents:
diff changeset
1759
kono
parents:
diff changeset
1760 There is no way to call a constructor of an ancestor sub-object in any
kono
parents:
diff changeset
1761 other way.
kono
parents:
diff changeset
1762
kono
parents:
diff changeset
1763 This means that we do not have to care whether constructors get the
kono
parents:
diff changeset
1764 correct type information because they will always change it (in fact,
kono
parents:
diff changeset
1765 if we define the type to be given by the VMT pointer, it is undefined).
kono
parents:
diff changeset
1766
kono
parents:
diff changeset
1767 The most important fact to derive from the above is that if, for some
kono
parents:
diff changeset
1768 statement in the section 3, we try to detect whether the dynamic type
kono
parents:
diff changeset
1769 has changed, we can safely ignore all calls as we examine the function
kono
parents:
diff changeset
1770 body backwards until we reach statements in section 2 because these
kono
parents:
diff changeset
1771 calls cannot be ancestor constructors or destructors (if the input is
kono
parents:
diff changeset
1772 not bogus) and so do not change the dynamic type (this holds true only
kono
parents:
diff changeset
1773 for automatically allocated objects but at the moment we devirtualize
kono
parents:
diff changeset
1774 only these). We then must detect that statements in section 2 change
kono
parents:
diff changeset
1775 the dynamic type and can try to derive the new type. That is enough
kono
parents:
diff changeset
1776 and we can stop, we will never see the calls into constructors of
kono
parents:
diff changeset
1777 sub-objects in this code.
kono
parents:
diff changeset
1778
kono
parents:
diff changeset
1779 Therefore if the static outer type was found (outer_type)
kono
parents:
diff changeset
1780 we can safely ignore tci.speculative that is set on calls and give up
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1781 only if there was dynamic type store that may affect given variable
111
kono
parents:
diff changeset
1782 (seen_unanalyzed_store) */
kono
parents:
diff changeset
1783
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1784 if (walked < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1785 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1786 if (dump_file)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1787 fprintf (dump_file, " AA walk budget exhausted.\n");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1788 *aa_walk_budget_p = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1789 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1790 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1791 else if (aa_walk_budget_p)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1792 *aa_walk_budget_p -= walked;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1793
111
kono
parents:
diff changeset
1794 if (!tci.type_maybe_changed
kono
parents:
diff changeset
1795 || (outer_type
kono
parents:
diff changeset
1796 && !dynamic
kono
parents:
diff changeset
1797 && !tci.seen_unanalyzed_store
kono
parents:
diff changeset
1798 && !tci.multiple_types_encountered
kono
parents:
diff changeset
1799 && ((offset == tci.offset
kono
parents:
diff changeset
1800 && types_same_for_odr (tci.known_current_type,
kono
parents:
diff changeset
1801 outer_type))
kono
parents:
diff changeset
1802 || (instance_offset == offset
kono
parents:
diff changeset
1803 && types_same_for_odr (tci.known_current_type,
kono
parents:
diff changeset
1804 instance_outer_type)))))
kono
parents:
diff changeset
1805 {
kono
parents:
diff changeset
1806 if (!outer_type || tci.seen_unanalyzed_store)
kono
parents:
diff changeset
1807 return false;
kono
parents:
diff changeset
1808 if (maybe_in_construction)
kono
parents:
diff changeset
1809 maybe_in_construction = false;
kono
parents:
diff changeset
1810 if (dump_file)
kono
parents:
diff changeset
1811 fprintf (dump_file, " No dynamic type change found.\n");
kono
parents:
diff changeset
1812 return true;
kono
parents:
diff changeset
1813 }
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 if (tci.known_current_type
kono
parents:
diff changeset
1816 && !function_entry_reached
kono
parents:
diff changeset
1817 && !tci.multiple_types_encountered)
kono
parents:
diff changeset
1818 {
kono
parents:
diff changeset
1819 if (!tci.speculative)
kono
parents:
diff changeset
1820 {
kono
parents:
diff changeset
1821 outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
kono
parents:
diff changeset
1822 offset = tci.known_current_offset;
kono
parents:
diff changeset
1823 dynamic = true;
kono
parents:
diff changeset
1824 maybe_in_construction = false;
kono
parents:
diff changeset
1825 maybe_derived_type = false;
kono
parents:
diff changeset
1826 if (dump_file)
kono
parents:
diff changeset
1827 fprintf (dump_file, " Determined dynamic type.\n");
kono
parents:
diff changeset
1828 }
kono
parents:
diff changeset
1829 else if (!speculative_outer_type
kono
parents:
diff changeset
1830 || speculative_maybe_derived_type)
kono
parents:
diff changeset
1831 {
kono
parents:
diff changeset
1832 speculative_outer_type = TYPE_MAIN_VARIANT (tci.known_current_type);
kono
parents:
diff changeset
1833 speculative_offset = tci.known_current_offset;
kono
parents:
diff changeset
1834 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
1835 if (dump_file)
kono
parents:
diff changeset
1836 fprintf (dump_file, " Determined speculative dynamic type.\n");
kono
parents:
diff changeset
1837 }
kono
parents:
diff changeset
1838 }
kono
parents:
diff changeset
1839 else if (dump_file)
kono
parents:
diff changeset
1840 {
kono
parents:
diff changeset
1841 fprintf (dump_file, " Found multiple types%s%s\n",
kono
parents:
diff changeset
1842 function_entry_reached ? " (function entry reached)" : "",
kono
parents:
diff changeset
1843 function_entry_reached ? " (multiple types encountered)" : "");
kono
parents:
diff changeset
1844 }
kono
parents:
diff changeset
1845
kono
parents:
diff changeset
1846 return false;
kono
parents:
diff changeset
1847 }
kono
parents:
diff changeset
1848
kono
parents:
diff changeset
1849 /* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
kono
parents:
diff changeset
1850 seems consistent (and useful) with what we already have in the non-speculative context. */
kono
parents:
diff changeset
1851
kono
parents:
diff changeset
1852 bool
kono
parents:
diff changeset
1853 ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type,
kono
parents:
diff changeset
1854 HOST_WIDE_INT spec_offset,
kono
parents:
diff changeset
1855 bool spec_maybe_derived_type,
kono
parents:
diff changeset
1856 tree otr_type) const
kono
parents:
diff changeset
1857 {
kono
parents:
diff changeset
1858 if (!flag_devirtualize_speculatively)
kono
parents:
diff changeset
1859 return false;
kono
parents:
diff changeset
1860
kono
parents:
diff changeset
1861 /* Non-polymorphic types are useless for deriving likely polymorphic
kono
parents:
diff changeset
1862 call targets. */
kono
parents:
diff changeset
1863 if (!spec_outer_type || !contains_polymorphic_type_p (spec_outer_type))
kono
parents:
diff changeset
1864 return false;
kono
parents:
diff changeset
1865
kono
parents:
diff changeset
1866 /* If we know nothing, speculation is always good. */
kono
parents:
diff changeset
1867 if (!outer_type)
kono
parents:
diff changeset
1868 return true;
kono
parents:
diff changeset
1869
kono
parents:
diff changeset
1870 /* Speculation is only useful to avoid derived types.
kono
parents:
diff changeset
1871 This is not 100% true for placement new, where the outer context may
kono
parents:
diff changeset
1872 turn out to be useless, but ignore these for now. */
kono
parents:
diff changeset
1873 if (!maybe_derived_type)
kono
parents:
diff changeset
1874 return false;
kono
parents:
diff changeset
1875
kono
parents:
diff changeset
1876 /* If types agrees, speculation is consistent, but it makes sense only
kono
parents:
diff changeset
1877 when it says something new. */
kono
parents:
diff changeset
1878 if (types_must_be_same_for_odr (spec_outer_type, outer_type))
kono
parents:
diff changeset
1879 return maybe_derived_type && !spec_maybe_derived_type;
kono
parents:
diff changeset
1880
kono
parents:
diff changeset
1881 /* If speculation does not contain the type in question, ignore it. */
kono
parents:
diff changeset
1882 if (otr_type
kono
parents:
diff changeset
1883 && !contains_type_p (spec_outer_type, spec_offset, otr_type, false, true))
kono
parents:
diff changeset
1884 return false;
kono
parents:
diff changeset
1885
kono
parents:
diff changeset
1886 /* If outer type already contains speculation as a filed,
kono
parents:
diff changeset
1887 it is useless. We already know from OUTER_TYPE
kono
parents:
diff changeset
1888 SPEC_TYPE and that it is not in the construction. */
kono
parents:
diff changeset
1889 if (contains_type_p (outer_type, offset - spec_offset,
kono
parents:
diff changeset
1890 spec_outer_type, false, false))
kono
parents:
diff changeset
1891 return false;
kono
parents:
diff changeset
1892
kono
parents:
diff changeset
1893 /* If speculative outer type is not more specified than outer
kono
parents:
diff changeset
1894 type, just give up.
kono
parents:
diff changeset
1895 We can only decide this safely if we can compare types with OUTER_TYPE.
kono
parents:
diff changeset
1896 */
kono
parents:
diff changeset
1897 if ((!in_lto_p || odr_type_p (outer_type))
kono
parents:
diff changeset
1898 && !contains_type_p (spec_outer_type,
kono
parents:
diff changeset
1899 spec_offset - offset,
kono
parents:
diff changeset
1900 outer_type, false))
kono
parents:
diff changeset
1901 return false;
kono
parents:
diff changeset
1902 return true;
kono
parents:
diff changeset
1903 }
kono
parents:
diff changeset
1904
kono
parents:
diff changeset
1905 /* Improve THIS with speculation described by NEW_OUTER_TYPE, NEW_OFFSET,
kono
parents:
diff changeset
1906 NEW_MAYBE_DERIVED_TYPE
kono
parents:
diff changeset
1907 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
kono
parents:
diff changeset
1908
kono
parents:
diff changeset
1909 bool
kono
parents:
diff changeset
1910 ipa_polymorphic_call_context::combine_speculation_with
kono
parents:
diff changeset
1911 (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
kono
parents:
diff changeset
1912 tree otr_type)
kono
parents:
diff changeset
1913 {
kono
parents:
diff changeset
1914 if (!new_outer_type)
kono
parents:
diff changeset
1915 return false;
kono
parents:
diff changeset
1916
kono
parents:
diff changeset
1917 /* restrict_to_inner_class may eliminate wrong speculation making our job
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1918 easier. */
111
kono
parents:
diff changeset
1919 if (otr_type)
kono
parents:
diff changeset
1920 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
1921
kono
parents:
diff changeset
1922 if (!speculation_consistent_p (new_outer_type, new_offset,
kono
parents:
diff changeset
1923 new_maybe_derived_type, otr_type))
kono
parents:
diff changeset
1924 return false;
kono
parents:
diff changeset
1925
kono
parents:
diff changeset
1926 /* New speculation is a win in case we have no speculation or new
kono
parents:
diff changeset
1927 speculation does not consider derivations. */
kono
parents:
diff changeset
1928 if (!speculative_outer_type
kono
parents:
diff changeset
1929 || (speculative_maybe_derived_type
kono
parents:
diff changeset
1930 && !new_maybe_derived_type))
kono
parents:
diff changeset
1931 {
kono
parents:
diff changeset
1932 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
1933 speculative_offset = new_offset;
kono
parents:
diff changeset
1934 speculative_maybe_derived_type = new_maybe_derived_type;
kono
parents:
diff changeset
1935 return true;
kono
parents:
diff changeset
1936 }
kono
parents:
diff changeset
1937 else if (types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
1938 new_outer_type))
kono
parents:
diff changeset
1939 {
kono
parents:
diff changeset
1940 if (speculative_offset != new_offset)
kono
parents:
diff changeset
1941 {
kono
parents:
diff changeset
1942 /* OK we have two contexts that seems valid but they disagree,
kono
parents:
diff changeset
1943 just give up.
kono
parents:
diff changeset
1944
kono
parents:
diff changeset
1945 This is not a lattice operation, so we may want to drop it later. */
kono
parents:
diff changeset
1946 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1947 fprintf (dump_file,
kono
parents:
diff changeset
1948 "Speculative outer types match, "
kono
parents:
diff changeset
1949 "offset mismatch -> invalid speculation\n");
kono
parents:
diff changeset
1950 clear_speculation ();
kono
parents:
diff changeset
1951 return true;
kono
parents:
diff changeset
1952 }
kono
parents:
diff changeset
1953 else
kono
parents:
diff changeset
1954 {
kono
parents:
diff changeset
1955 if (speculative_maybe_derived_type && !new_maybe_derived_type)
kono
parents:
diff changeset
1956 {
kono
parents:
diff changeset
1957 speculative_maybe_derived_type = false;
kono
parents:
diff changeset
1958 return true;
kono
parents:
diff changeset
1959 }
kono
parents:
diff changeset
1960 else
kono
parents:
diff changeset
1961 return false;
kono
parents:
diff changeset
1962 }
kono
parents:
diff changeset
1963 }
kono
parents:
diff changeset
1964 /* Choose type that contains the other. This one either contains the outer
kono
parents:
diff changeset
1965 as a field (thus giving exactly one target) or is deeper in the type
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1966 hierarchy. */
111
kono
parents:
diff changeset
1967 else if (speculative_outer_type
kono
parents:
diff changeset
1968 && speculative_maybe_derived_type
kono
parents:
diff changeset
1969 && (new_offset > speculative_offset
kono
parents:
diff changeset
1970 || (new_offset == speculative_offset
kono
parents:
diff changeset
1971 && contains_type_p (new_outer_type,
kono
parents:
diff changeset
1972 0, speculative_outer_type, false))))
kono
parents:
diff changeset
1973 {
kono
parents:
diff changeset
1974 tree old_outer_type = speculative_outer_type;
kono
parents:
diff changeset
1975 HOST_WIDE_INT old_offset = speculative_offset;
kono
parents:
diff changeset
1976 bool old_maybe_derived_type = speculative_maybe_derived_type;
kono
parents:
diff changeset
1977
kono
parents:
diff changeset
1978 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
1979 speculative_offset = new_offset;
kono
parents:
diff changeset
1980 speculative_maybe_derived_type = new_maybe_derived_type;
kono
parents:
diff changeset
1981
kono
parents:
diff changeset
1982 if (otr_type)
kono
parents:
diff changeset
1983 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
1984
kono
parents:
diff changeset
1985 /* If the speculation turned out to make no sense, revert to sensible
kono
parents:
diff changeset
1986 one. */
kono
parents:
diff changeset
1987 if (!speculative_outer_type)
kono
parents:
diff changeset
1988 {
kono
parents:
diff changeset
1989 speculative_outer_type = old_outer_type;
kono
parents:
diff changeset
1990 speculative_offset = old_offset;
kono
parents:
diff changeset
1991 speculative_maybe_derived_type = old_maybe_derived_type;
kono
parents:
diff changeset
1992 return false;
kono
parents:
diff changeset
1993 }
kono
parents:
diff changeset
1994 return (old_offset != speculative_offset
kono
parents:
diff changeset
1995 || old_maybe_derived_type != speculative_maybe_derived_type
kono
parents:
diff changeset
1996 || types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
1997 new_outer_type));
kono
parents:
diff changeset
1998 }
kono
parents:
diff changeset
1999 return false;
kono
parents:
diff changeset
2000 }
kono
parents:
diff changeset
2001
kono
parents:
diff changeset
2002 /* Make speculation less specific so
kono
parents:
diff changeset
2003 NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included.
kono
parents:
diff changeset
2004 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
kono
parents:
diff changeset
2005
kono
parents:
diff changeset
2006 bool
kono
parents:
diff changeset
2007 ipa_polymorphic_call_context::meet_speculation_with
kono
parents:
diff changeset
2008 (tree new_outer_type, HOST_WIDE_INT new_offset, bool new_maybe_derived_type,
kono
parents:
diff changeset
2009 tree otr_type)
kono
parents:
diff changeset
2010 {
kono
parents:
diff changeset
2011 if (!new_outer_type && speculative_outer_type)
kono
parents:
diff changeset
2012 {
kono
parents:
diff changeset
2013 clear_speculation ();
kono
parents:
diff changeset
2014 return true;
kono
parents:
diff changeset
2015 }
kono
parents:
diff changeset
2016
kono
parents:
diff changeset
2017 /* restrict_to_inner_class may eliminate wrong speculation making our job
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2018 easier. */
111
kono
parents:
diff changeset
2019 if (otr_type)
kono
parents:
diff changeset
2020 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2021
kono
parents:
diff changeset
2022 if (!speculative_outer_type
kono
parents:
diff changeset
2023 || !speculation_consistent_p (speculative_outer_type,
kono
parents:
diff changeset
2024 speculative_offset,
kono
parents:
diff changeset
2025 speculative_maybe_derived_type,
kono
parents:
diff changeset
2026 otr_type))
kono
parents:
diff changeset
2027 return false;
kono
parents:
diff changeset
2028
kono
parents:
diff changeset
2029 if (!speculation_consistent_p (new_outer_type, new_offset,
kono
parents:
diff changeset
2030 new_maybe_derived_type, otr_type))
kono
parents:
diff changeset
2031 {
kono
parents:
diff changeset
2032 clear_speculation ();
kono
parents:
diff changeset
2033 return true;
kono
parents:
diff changeset
2034 }
kono
parents:
diff changeset
2035
kono
parents:
diff changeset
2036 else if (types_must_be_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
2037 new_outer_type))
kono
parents:
diff changeset
2038 {
kono
parents:
diff changeset
2039 if (speculative_offset != new_offset)
kono
parents:
diff changeset
2040 {
kono
parents:
diff changeset
2041 clear_speculation ();
kono
parents:
diff changeset
2042 return true;
kono
parents:
diff changeset
2043 }
kono
parents:
diff changeset
2044 else
kono
parents:
diff changeset
2045 {
kono
parents:
diff changeset
2046 if (!speculative_maybe_derived_type && new_maybe_derived_type)
kono
parents:
diff changeset
2047 {
kono
parents:
diff changeset
2048 speculative_maybe_derived_type = true;
kono
parents:
diff changeset
2049 return true;
kono
parents:
diff changeset
2050 }
kono
parents:
diff changeset
2051 else
kono
parents:
diff changeset
2052 return false;
kono
parents:
diff changeset
2053 }
kono
parents:
diff changeset
2054 }
kono
parents:
diff changeset
2055 /* See if one type contains the other as a field (not base). */
kono
parents:
diff changeset
2056 else if (contains_type_p (new_outer_type, new_offset - speculative_offset,
kono
parents:
diff changeset
2057 speculative_outer_type, false, false))
kono
parents:
diff changeset
2058 return false;
kono
parents:
diff changeset
2059 else if (contains_type_p (speculative_outer_type,
kono
parents:
diff changeset
2060 speculative_offset - new_offset,
kono
parents:
diff changeset
2061 new_outer_type, false, false))
kono
parents:
diff changeset
2062 {
kono
parents:
diff changeset
2063 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
2064 speculative_offset = new_offset;
kono
parents:
diff changeset
2065 speculative_maybe_derived_type = new_maybe_derived_type;
kono
parents:
diff changeset
2066 return true;
kono
parents:
diff changeset
2067 }
kono
parents:
diff changeset
2068 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
kono
parents:
diff changeset
2069 else if (contains_type_p (new_outer_type,
kono
parents:
diff changeset
2070 new_offset - speculative_offset,
kono
parents:
diff changeset
2071 speculative_outer_type, false, true))
kono
parents:
diff changeset
2072 {
kono
parents:
diff changeset
2073 if (!speculative_maybe_derived_type)
kono
parents:
diff changeset
2074 {
kono
parents:
diff changeset
2075 speculative_maybe_derived_type = true;
kono
parents:
diff changeset
2076 return true;
kono
parents:
diff changeset
2077 }
kono
parents:
diff changeset
2078 return false;
kono
parents:
diff changeset
2079 }
kono
parents:
diff changeset
2080 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
kono
parents:
diff changeset
2081 else if (contains_type_p (speculative_outer_type,
kono
parents:
diff changeset
2082 speculative_offset - new_offset, new_outer_type, false, true))
kono
parents:
diff changeset
2083 {
kono
parents:
diff changeset
2084 speculative_outer_type = new_outer_type;
kono
parents:
diff changeset
2085 speculative_offset = new_offset;
kono
parents:
diff changeset
2086 speculative_maybe_derived_type = true;
kono
parents:
diff changeset
2087 return true;
kono
parents:
diff changeset
2088 }
kono
parents:
diff changeset
2089 else
kono
parents:
diff changeset
2090 {
kono
parents:
diff changeset
2091 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2092 fprintf (dump_file, "Giving up on speculative meet\n");
kono
parents:
diff changeset
2093 clear_speculation ();
kono
parents:
diff changeset
2094 return true;
kono
parents:
diff changeset
2095 }
kono
parents:
diff changeset
2096 }
kono
parents:
diff changeset
2097
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2098 /* Assume that both THIS and a given context is valid and strengthen THIS
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2099 if possible. Return true if any strengthening was made.
111
kono
parents:
diff changeset
2100 If actual type the context is being used in is known, OTR_TYPE should be
kono
parents:
diff changeset
2101 set accordingly. This improves quality of combined result. */
kono
parents:
diff changeset
2102
kono
parents:
diff changeset
2103 bool
kono
parents:
diff changeset
2104 ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx,
kono
parents:
diff changeset
2105 tree otr_type)
kono
parents:
diff changeset
2106 {
kono
parents:
diff changeset
2107 bool updated = false;
kono
parents:
diff changeset
2108
kono
parents:
diff changeset
2109 if (ctx.useless_p () || invalid)
kono
parents:
diff changeset
2110 return false;
kono
parents:
diff changeset
2111
kono
parents:
diff changeset
2112 /* Restricting context to inner type makes merging easier, however do not
kono
parents:
diff changeset
2113 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
kono
parents:
diff changeset
2114 if (otr_type && !invalid && !ctx.invalid)
kono
parents:
diff changeset
2115 {
kono
parents:
diff changeset
2116 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2117 ctx.restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2118 if(invalid)
kono
parents:
diff changeset
2119 return false;
kono
parents:
diff changeset
2120 }
kono
parents:
diff changeset
2121
kono
parents:
diff changeset
2122 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2123 {
kono
parents:
diff changeset
2124 fprintf (dump_file, "Polymorphic call context combine:");
kono
parents:
diff changeset
2125 dump (dump_file);
kono
parents:
diff changeset
2126 fprintf (dump_file, "With context: ");
kono
parents:
diff changeset
2127 ctx.dump (dump_file);
kono
parents:
diff changeset
2128 if (otr_type)
kono
parents:
diff changeset
2129 {
kono
parents:
diff changeset
2130 fprintf (dump_file, "To be used with type: ");
kono
parents:
diff changeset
2131 print_generic_expr (dump_file, otr_type, TDF_SLIM);
kono
parents:
diff changeset
2132 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2133 }
kono
parents:
diff changeset
2134 }
kono
parents:
diff changeset
2135
kono
parents:
diff changeset
2136 /* If call is known to be invalid, we are done. */
kono
parents:
diff changeset
2137 if (ctx.invalid)
kono
parents:
diff changeset
2138 {
kono
parents:
diff changeset
2139 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2140 fprintf (dump_file, "-> Invalid context\n");
kono
parents:
diff changeset
2141 goto invalidate;
kono
parents:
diff changeset
2142 }
kono
parents:
diff changeset
2143
kono
parents:
diff changeset
2144 if (!ctx.outer_type)
kono
parents:
diff changeset
2145 ;
kono
parents:
diff changeset
2146 else if (!outer_type)
kono
parents:
diff changeset
2147 {
kono
parents:
diff changeset
2148 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2149 offset = ctx.offset;
kono
parents:
diff changeset
2150 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2151 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2152 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2153 updated = true;
kono
parents:
diff changeset
2154 }
kono
parents:
diff changeset
2155 /* If types are known to be same, merging is quite easy. */
kono
parents:
diff changeset
2156 else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2157 {
kono
parents:
diff changeset
2158 if (offset != ctx.offset
kono
parents:
diff changeset
2159 && TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2160 && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
kono
parents:
diff changeset
2161 {
kono
parents:
diff changeset
2162 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2163 fprintf (dump_file, "Outer types match, offset mismatch -> invalid\n");
kono
parents:
diff changeset
2164 clear_speculation ();
kono
parents:
diff changeset
2165 clear_outer_type ();
kono
parents:
diff changeset
2166 invalid = true;
kono
parents:
diff changeset
2167 return true;
kono
parents:
diff changeset
2168 }
kono
parents:
diff changeset
2169 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2170 fprintf (dump_file, "Outer types match, merging flags\n");
kono
parents:
diff changeset
2171 if (maybe_in_construction && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2172 {
kono
parents:
diff changeset
2173 updated = true;
kono
parents:
diff changeset
2174 maybe_in_construction = false;
kono
parents:
diff changeset
2175 }
kono
parents:
diff changeset
2176 if (maybe_derived_type && !ctx.maybe_derived_type)
kono
parents:
diff changeset
2177 {
kono
parents:
diff changeset
2178 updated = true;
kono
parents:
diff changeset
2179 maybe_derived_type = false;
kono
parents:
diff changeset
2180 }
kono
parents:
diff changeset
2181 if (dynamic && !ctx.dynamic)
kono
parents:
diff changeset
2182 {
kono
parents:
diff changeset
2183 updated = true;
kono
parents:
diff changeset
2184 dynamic = false;
kono
parents:
diff changeset
2185 }
kono
parents:
diff changeset
2186 }
kono
parents:
diff changeset
2187 /* If we know the type precisely, there is not much to improve. */
kono
parents:
diff changeset
2188 else if (!maybe_derived_type && !maybe_in_construction
kono
parents:
diff changeset
2189 && !ctx.maybe_derived_type && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2190 {
kono
parents:
diff changeset
2191 /* It may be easy to check if second context permits the first
kono
parents:
diff changeset
2192 and set INVALID otherwise. This is not easy to do in general;
kono
parents:
diff changeset
2193 contains_type_p may return false negatives for non-comparable
kono
parents:
diff changeset
2194 types.
kono
parents:
diff changeset
2195
kono
parents:
diff changeset
2196 If OTR_TYPE is known, we however can expect that
kono
parents:
diff changeset
2197 restrict_to_inner_class should have discovered the same base
kono
parents:
diff changeset
2198 type. */
kono
parents:
diff changeset
2199 if (otr_type && !ctx.maybe_in_construction && !ctx.maybe_derived_type)
kono
parents:
diff changeset
2200 {
kono
parents:
diff changeset
2201 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2202 fprintf (dump_file, "Contextes disagree -> invalid\n");
kono
parents:
diff changeset
2203 goto invalidate;
kono
parents:
diff changeset
2204 }
kono
parents:
diff changeset
2205 }
kono
parents:
diff changeset
2206 /* See if one type contains the other as a field (not base).
kono
parents:
diff changeset
2207 In this case we want to choose the wider type, because it contains
kono
parents:
diff changeset
2208 more information. */
kono
parents:
diff changeset
2209 else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
kono
parents:
diff changeset
2210 outer_type, false, false))
kono
parents:
diff changeset
2211 {
kono
parents:
diff changeset
2212 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2213 fprintf (dump_file, "Second type contain the first as a field\n");
kono
parents:
diff changeset
2214
kono
parents:
diff changeset
2215 if (maybe_derived_type)
kono
parents:
diff changeset
2216 {
kono
parents:
diff changeset
2217 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2218 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2219 offset = ctx.offset;
kono
parents:
diff changeset
2220 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2221 updated = true;
kono
parents:
diff changeset
2222 }
kono
parents:
diff changeset
2223
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2224 /* If we do not know how the context is being used, we cannot
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2225 clear MAYBE_IN_CONSTRUCTION because it may be offseted
111
kono
parents:
diff changeset
2226 to other component of OUTER_TYPE later and we know nothing
kono
parents:
diff changeset
2227 about it. */
kono
parents:
diff changeset
2228 if (otr_type && maybe_in_construction
kono
parents:
diff changeset
2229 && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2230 {
kono
parents:
diff changeset
2231 maybe_in_construction = false;
kono
parents:
diff changeset
2232 updated = true;
kono
parents:
diff changeset
2233 }
kono
parents:
diff changeset
2234 }
kono
parents:
diff changeset
2235 else if (contains_type_p (outer_type, offset - ctx.offset,
kono
parents:
diff changeset
2236 ctx.outer_type, false, false))
kono
parents:
diff changeset
2237 {
kono
parents:
diff changeset
2238 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2239 fprintf (dump_file, "First type contain the second as a field\n");
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 if (otr_type && maybe_in_construction
kono
parents:
diff changeset
2242 && !ctx.maybe_in_construction)
kono
parents:
diff changeset
2243 {
kono
parents:
diff changeset
2244 maybe_in_construction = false;
kono
parents:
diff changeset
2245 updated = true;
kono
parents:
diff changeset
2246 }
kono
parents:
diff changeset
2247 }
kono
parents:
diff changeset
2248 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
kono
parents:
diff changeset
2249 else if (contains_type_p (ctx.outer_type,
kono
parents:
diff changeset
2250 ctx.offset - offset, outer_type, false, true))
kono
parents:
diff changeset
2251 {
kono
parents:
diff changeset
2252 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2253 fprintf (dump_file, "First type is base of second\n");
kono
parents:
diff changeset
2254 if (!maybe_derived_type)
kono
parents:
diff changeset
2255 {
kono
parents:
diff changeset
2256 if (!ctx.maybe_in_construction
kono
parents:
diff changeset
2257 && types_odr_comparable (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2258 {
kono
parents:
diff changeset
2259 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2260 fprintf (dump_file, "Second context does not permit base -> invalid\n");
kono
parents:
diff changeset
2261 goto invalidate;
kono
parents:
diff changeset
2262 }
kono
parents:
diff changeset
2263 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2264 /* Pick variant deeper in the hierarchy. */
111
kono
parents:
diff changeset
2265 else
kono
parents:
diff changeset
2266 {
kono
parents:
diff changeset
2267 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2268 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2269 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2270 offset = ctx.offset;
kono
parents:
diff changeset
2271 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2272 updated = true;
kono
parents:
diff changeset
2273 }
kono
parents:
diff changeset
2274 }
kono
parents:
diff changeset
2275 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
kono
parents:
diff changeset
2276 else if (contains_type_p (outer_type,
kono
parents:
diff changeset
2277 offset - ctx.offset, ctx.outer_type, false, true))
kono
parents:
diff changeset
2278 {
kono
parents:
diff changeset
2279 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2280 fprintf (dump_file, "Second type is base of first\n");
kono
parents:
diff changeset
2281 if (!ctx.maybe_derived_type)
kono
parents:
diff changeset
2282 {
kono
parents:
diff changeset
2283 if (!maybe_in_construction
kono
parents:
diff changeset
2284 && types_odr_comparable (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2285 {
kono
parents:
diff changeset
2286 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2287 fprintf (dump_file, "First context does not permit base -> invalid\n");
kono
parents:
diff changeset
2288 goto invalidate;
kono
parents:
diff changeset
2289 }
kono
parents:
diff changeset
2290 /* Pick the base type. */
kono
parents:
diff changeset
2291 else if (maybe_in_construction)
kono
parents:
diff changeset
2292 {
kono
parents:
diff changeset
2293 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2294 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2295 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2296 offset = ctx.offset;
kono
parents:
diff changeset
2297 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2298 updated = true;
kono
parents:
diff changeset
2299 }
kono
parents:
diff changeset
2300 }
kono
parents:
diff changeset
2301 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2302 /* TODO handle merging using hierarchy. */
111
kono
parents:
diff changeset
2303 else if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2304 fprintf (dump_file, "Giving up on merge\n");
kono
parents:
diff changeset
2305
kono
parents:
diff changeset
2306 updated |= combine_speculation_with (ctx.speculative_outer_type,
kono
parents:
diff changeset
2307 ctx.speculative_offset,
kono
parents:
diff changeset
2308 ctx.speculative_maybe_derived_type,
kono
parents:
diff changeset
2309 otr_type);
kono
parents:
diff changeset
2310
kono
parents:
diff changeset
2311 if (updated && dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2312 {
kono
parents:
diff changeset
2313 fprintf (dump_file, "Updated as: ");
kono
parents:
diff changeset
2314 dump (dump_file);
kono
parents:
diff changeset
2315 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2316 }
kono
parents:
diff changeset
2317 return updated;
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 invalidate:
kono
parents:
diff changeset
2320 invalid = true;
kono
parents:
diff changeset
2321 clear_speculation ();
kono
parents:
diff changeset
2322 clear_outer_type ();
kono
parents:
diff changeset
2323 return true;
kono
parents:
diff changeset
2324 }
kono
parents:
diff changeset
2325
kono
parents:
diff changeset
2326 /* Take non-speculative info, merge it with speculative and clear speculation.
kono
parents:
diff changeset
2327 Used when we no longer manage to keep track of actual outer type, but we
kono
parents:
diff changeset
2328 think it is still there.
kono
parents:
diff changeset
2329
kono
parents:
diff changeset
2330 If OTR_TYPE is set, the transformation can be done more effectively assuming
kono
parents:
diff changeset
2331 that context is going to be used only that way. */
kono
parents:
diff changeset
2332
kono
parents:
diff changeset
2333 void
kono
parents:
diff changeset
2334 ipa_polymorphic_call_context::make_speculative (tree otr_type)
kono
parents:
diff changeset
2335 {
kono
parents:
diff changeset
2336 tree spec_outer_type = outer_type;
kono
parents:
diff changeset
2337 HOST_WIDE_INT spec_offset = offset;
kono
parents:
diff changeset
2338 bool spec_maybe_derived_type = maybe_derived_type;
kono
parents:
diff changeset
2339
kono
parents:
diff changeset
2340 if (invalid)
kono
parents:
diff changeset
2341 {
kono
parents:
diff changeset
2342 invalid = false;
kono
parents:
diff changeset
2343 clear_outer_type ();
kono
parents:
diff changeset
2344 clear_speculation ();
kono
parents:
diff changeset
2345 return;
kono
parents:
diff changeset
2346 }
kono
parents:
diff changeset
2347 if (!outer_type)
kono
parents:
diff changeset
2348 return;
kono
parents:
diff changeset
2349 clear_outer_type ();
kono
parents:
diff changeset
2350 combine_speculation_with (spec_outer_type, spec_offset,
kono
parents:
diff changeset
2351 spec_maybe_derived_type,
kono
parents:
diff changeset
2352 otr_type);
kono
parents:
diff changeset
2353 }
kono
parents:
diff changeset
2354
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2355 /* Use when we cannot track dynamic type change. This speculatively assume
111
kono
parents:
diff changeset
2356 type change is not happening. */
kono
parents:
diff changeset
2357
kono
parents:
diff changeset
2358 void
kono
parents:
diff changeset
2359 ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
kono
parents:
diff changeset
2360 tree otr_type)
kono
parents:
diff changeset
2361 {
kono
parents:
diff changeset
2362 if (dynamic)
kono
parents:
diff changeset
2363 make_speculative (otr_type);
kono
parents:
diff changeset
2364 else if (in_poly_cdtor)
kono
parents:
diff changeset
2365 maybe_in_construction = true;
kono
parents:
diff changeset
2366 }
kono
parents:
diff changeset
2367
kono
parents:
diff changeset
2368 /* Return TRUE if this context conveys the same information as OTHER. */
kono
parents:
diff changeset
2369
kono
parents:
diff changeset
2370 bool
kono
parents:
diff changeset
2371 ipa_polymorphic_call_context::equal_to
kono
parents:
diff changeset
2372 (const ipa_polymorphic_call_context &x) const
kono
parents:
diff changeset
2373 {
kono
parents:
diff changeset
2374 if (useless_p ())
kono
parents:
diff changeset
2375 return x.useless_p ();
kono
parents:
diff changeset
2376 if (invalid)
kono
parents:
diff changeset
2377 return x.invalid;
kono
parents:
diff changeset
2378 if (x.useless_p () || x.invalid)
kono
parents:
diff changeset
2379 return false;
kono
parents:
diff changeset
2380
kono
parents:
diff changeset
2381 if (outer_type)
kono
parents:
diff changeset
2382 {
kono
parents:
diff changeset
2383 if (!x.outer_type
kono
parents:
diff changeset
2384 || !types_odr_comparable (outer_type, x.outer_type)
kono
parents:
diff changeset
2385 || !types_same_for_odr (outer_type, x.outer_type)
kono
parents:
diff changeset
2386 || offset != x.offset
kono
parents:
diff changeset
2387 || maybe_in_construction != x.maybe_in_construction
kono
parents:
diff changeset
2388 || maybe_derived_type != x.maybe_derived_type
kono
parents:
diff changeset
2389 || dynamic != x.dynamic)
kono
parents:
diff changeset
2390 return false;
kono
parents:
diff changeset
2391 }
kono
parents:
diff changeset
2392 else if (x.outer_type)
kono
parents:
diff changeset
2393 return false;
kono
parents:
diff changeset
2394
kono
parents:
diff changeset
2395
kono
parents:
diff changeset
2396 if (speculative_outer_type
kono
parents:
diff changeset
2397 && speculation_consistent_p (speculative_outer_type, speculative_offset,
kono
parents:
diff changeset
2398 speculative_maybe_derived_type, NULL_TREE))
kono
parents:
diff changeset
2399 {
kono
parents:
diff changeset
2400 if (!x.speculative_outer_type)
kono
parents:
diff changeset
2401 return false;
kono
parents:
diff changeset
2402
kono
parents:
diff changeset
2403 if (!types_odr_comparable (speculative_outer_type,
kono
parents:
diff changeset
2404 x.speculative_outer_type)
kono
parents:
diff changeset
2405 || !types_same_for_odr (speculative_outer_type,
kono
parents:
diff changeset
2406 x.speculative_outer_type)
kono
parents:
diff changeset
2407 || speculative_offset != x.speculative_offset
kono
parents:
diff changeset
2408 || speculative_maybe_derived_type != x.speculative_maybe_derived_type)
kono
parents:
diff changeset
2409 return false;
kono
parents:
diff changeset
2410 }
kono
parents:
diff changeset
2411 else if (x.speculative_outer_type
kono
parents:
diff changeset
2412 && x.speculation_consistent_p (x.speculative_outer_type,
kono
parents:
diff changeset
2413 x.speculative_offset,
kono
parents:
diff changeset
2414 x.speculative_maybe_derived_type,
kono
parents:
diff changeset
2415 NULL))
kono
parents:
diff changeset
2416 return false;
kono
parents:
diff changeset
2417
kono
parents:
diff changeset
2418 return true;
kono
parents:
diff changeset
2419 }
kono
parents:
diff changeset
2420
kono
parents:
diff changeset
2421 /* Modify context to be strictly less restrictive than CTX. */
kono
parents:
diff changeset
2422
kono
parents:
diff changeset
2423 bool
kono
parents:
diff changeset
2424 ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx,
kono
parents:
diff changeset
2425 tree otr_type)
kono
parents:
diff changeset
2426 {
kono
parents:
diff changeset
2427 bool updated = false;
kono
parents:
diff changeset
2428
kono
parents:
diff changeset
2429 if (useless_p () || ctx.invalid)
kono
parents:
diff changeset
2430 return false;
kono
parents:
diff changeset
2431
kono
parents:
diff changeset
2432 /* Restricting context to inner type makes merging easier, however do not
kono
parents:
diff changeset
2433 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
kono
parents:
diff changeset
2434 if (otr_type && !useless_p () && !ctx.useless_p ())
kono
parents:
diff changeset
2435 {
kono
parents:
diff changeset
2436 restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2437 ctx.restrict_to_inner_class (otr_type);
kono
parents:
diff changeset
2438 if(invalid)
kono
parents:
diff changeset
2439 return false;
kono
parents:
diff changeset
2440 }
kono
parents:
diff changeset
2441
kono
parents:
diff changeset
2442 if (equal_to (ctx))
kono
parents:
diff changeset
2443 return false;
kono
parents:
diff changeset
2444
kono
parents:
diff changeset
2445 if (ctx.useless_p () || invalid)
kono
parents:
diff changeset
2446 {
kono
parents:
diff changeset
2447 *this = ctx;
kono
parents:
diff changeset
2448 return true;
kono
parents:
diff changeset
2449 }
kono
parents:
diff changeset
2450
kono
parents:
diff changeset
2451 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2452 {
kono
parents:
diff changeset
2453 fprintf (dump_file, "Polymorphic call context meet:");
kono
parents:
diff changeset
2454 dump (dump_file);
kono
parents:
diff changeset
2455 fprintf (dump_file, "With context: ");
kono
parents:
diff changeset
2456 ctx.dump (dump_file);
kono
parents:
diff changeset
2457 if (otr_type)
kono
parents:
diff changeset
2458 {
kono
parents:
diff changeset
2459 fprintf (dump_file, "To be used with type: ");
kono
parents:
diff changeset
2460 print_generic_expr (dump_file, otr_type, TDF_SLIM);
kono
parents:
diff changeset
2461 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2462 }
kono
parents:
diff changeset
2463 }
kono
parents:
diff changeset
2464
kono
parents:
diff changeset
2465 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2466 {
kono
parents:
diff changeset
2467 dynamic = true;
kono
parents:
diff changeset
2468 updated = true;
kono
parents:
diff changeset
2469 }
kono
parents:
diff changeset
2470
kono
parents:
diff changeset
2471 /* If call is known to be invalid, we are done. */
kono
parents:
diff changeset
2472 if (!outer_type)
kono
parents:
diff changeset
2473 ;
kono
parents:
diff changeset
2474 else if (!ctx.outer_type)
kono
parents:
diff changeset
2475 {
kono
parents:
diff changeset
2476 clear_outer_type ();
kono
parents:
diff changeset
2477 updated = true;
kono
parents:
diff changeset
2478 }
kono
parents:
diff changeset
2479 /* If types are known to be same, merging is quite easy. */
kono
parents:
diff changeset
2480 else if (types_must_be_same_for_odr (outer_type, ctx.outer_type))
kono
parents:
diff changeset
2481 {
kono
parents:
diff changeset
2482 if (offset != ctx.offset
kono
parents:
diff changeset
2483 && TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2484 && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST)
kono
parents:
diff changeset
2485 {
kono
parents:
diff changeset
2486 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2487 fprintf (dump_file, "Outer types match, offset mismatch -> clearing\n");
kono
parents:
diff changeset
2488 clear_outer_type ();
kono
parents:
diff changeset
2489 return true;
kono
parents:
diff changeset
2490 }
kono
parents:
diff changeset
2491 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2492 fprintf (dump_file, "Outer types match, merging flags\n");
kono
parents:
diff changeset
2493 if (!maybe_in_construction && ctx.maybe_in_construction)
kono
parents:
diff changeset
2494 {
kono
parents:
diff changeset
2495 updated = true;
kono
parents:
diff changeset
2496 maybe_in_construction = true;
kono
parents:
diff changeset
2497 }
kono
parents:
diff changeset
2498 if (!maybe_derived_type && ctx.maybe_derived_type)
kono
parents:
diff changeset
2499 {
kono
parents:
diff changeset
2500 updated = true;
kono
parents:
diff changeset
2501 maybe_derived_type = true;
kono
parents:
diff changeset
2502 }
kono
parents:
diff changeset
2503 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2504 {
kono
parents:
diff changeset
2505 updated = true;
kono
parents:
diff changeset
2506 dynamic = true;
kono
parents:
diff changeset
2507 }
kono
parents:
diff changeset
2508 }
kono
parents:
diff changeset
2509 /* See if one type contains the other as a field (not base). */
kono
parents:
diff changeset
2510 else if (contains_type_p (ctx.outer_type, ctx.offset - offset,
kono
parents:
diff changeset
2511 outer_type, false, false))
kono
parents:
diff changeset
2512 {
kono
parents:
diff changeset
2513 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2514 fprintf (dump_file, "Second type contain the first as a field\n");
kono
parents:
diff changeset
2515
kono
parents:
diff changeset
2516 /* The second type is more specified, so we keep the first.
kono
parents:
diff changeset
2517 We need to set DYNAMIC flag to avoid declaring context INVALID
kono
parents:
diff changeset
2518 of OFFSET ends up being out of range. */
kono
parents:
diff changeset
2519 if (!dynamic
kono
parents:
diff changeset
2520 && (ctx.dynamic
kono
parents:
diff changeset
2521 || (!otr_type
kono
parents:
diff changeset
2522 && (!TYPE_SIZE (ctx.outer_type)
kono
parents:
diff changeset
2523 || !TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2524 || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
kono
parents:
diff changeset
2525 TYPE_SIZE (outer_type), 0)))))
kono
parents:
diff changeset
2526 {
kono
parents:
diff changeset
2527 dynamic = true;
kono
parents:
diff changeset
2528 updated = true;
kono
parents:
diff changeset
2529 }
kono
parents:
diff changeset
2530 }
kono
parents:
diff changeset
2531 else if (contains_type_p (outer_type, offset - ctx.offset,
kono
parents:
diff changeset
2532 ctx.outer_type, false, false))
kono
parents:
diff changeset
2533 {
kono
parents:
diff changeset
2534 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2535 fprintf (dump_file, "First type contain the second as a field\n");
kono
parents:
diff changeset
2536
kono
parents:
diff changeset
2537 if (!dynamic
kono
parents:
diff changeset
2538 && (ctx.dynamic
kono
parents:
diff changeset
2539 || (!otr_type
kono
parents:
diff changeset
2540 && (!TYPE_SIZE (ctx.outer_type)
kono
parents:
diff changeset
2541 || !TYPE_SIZE (outer_type)
kono
parents:
diff changeset
2542 || !operand_equal_p (TYPE_SIZE (ctx.outer_type),
kono
parents:
diff changeset
2543 TYPE_SIZE (outer_type), 0)))))
kono
parents:
diff changeset
2544 dynamic = true;
kono
parents:
diff changeset
2545 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2546 offset = ctx.offset;
kono
parents:
diff changeset
2547 dynamic = ctx.dynamic;
kono
parents:
diff changeset
2548 maybe_in_construction = ctx.maybe_in_construction;
kono
parents:
diff changeset
2549 maybe_derived_type = ctx.maybe_derived_type;
kono
parents:
diff changeset
2550 updated = true;
kono
parents:
diff changeset
2551 }
kono
parents:
diff changeset
2552 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
kono
parents:
diff changeset
2553 else if (contains_type_p (ctx.outer_type,
kono
parents:
diff changeset
2554 ctx.offset - offset, outer_type, false, true))
kono
parents:
diff changeset
2555 {
kono
parents:
diff changeset
2556 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2557 fprintf (dump_file, "First type is base of second\n");
kono
parents:
diff changeset
2558 if (!maybe_derived_type)
kono
parents:
diff changeset
2559 {
kono
parents:
diff changeset
2560 maybe_derived_type = true;
kono
parents:
diff changeset
2561 updated = true;
kono
parents:
diff changeset
2562 }
kono
parents:
diff changeset
2563 if (!maybe_in_construction && ctx.maybe_in_construction)
kono
parents:
diff changeset
2564 {
kono
parents:
diff changeset
2565 maybe_in_construction = true;
kono
parents:
diff changeset
2566 updated = true;
kono
parents:
diff changeset
2567 }
kono
parents:
diff changeset
2568 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2569 {
kono
parents:
diff changeset
2570 dynamic = true;
kono
parents:
diff changeset
2571 updated = true;
kono
parents:
diff changeset
2572 }
kono
parents:
diff changeset
2573 }
kono
parents:
diff changeset
2574 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
kono
parents:
diff changeset
2575 else if (contains_type_p (outer_type,
kono
parents:
diff changeset
2576 offset - ctx.offset, ctx.outer_type, false, true))
kono
parents:
diff changeset
2577 {
kono
parents:
diff changeset
2578 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2579 fprintf (dump_file, "Second type is base of first\n");
kono
parents:
diff changeset
2580 outer_type = ctx.outer_type;
kono
parents:
diff changeset
2581 offset = ctx.offset;
kono
parents:
diff changeset
2582 updated = true;
kono
parents:
diff changeset
2583 if (!maybe_derived_type)
kono
parents:
diff changeset
2584 maybe_derived_type = true;
kono
parents:
diff changeset
2585 if (!maybe_in_construction && ctx.maybe_in_construction)
kono
parents:
diff changeset
2586 maybe_in_construction = true;
kono
parents:
diff changeset
2587 if (!dynamic && ctx.dynamic)
kono
parents:
diff changeset
2588 dynamic = true;
kono
parents:
diff changeset
2589 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2590 /* TODO handle merging using hierarchy. */
111
kono
parents:
diff changeset
2591 else
kono
parents:
diff changeset
2592 {
kono
parents:
diff changeset
2593 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2594 fprintf (dump_file, "Giving up on meet\n");
kono
parents:
diff changeset
2595 clear_outer_type ();
kono
parents:
diff changeset
2596 updated = true;
kono
parents:
diff changeset
2597 }
kono
parents:
diff changeset
2598
kono
parents:
diff changeset
2599 updated |= meet_speculation_with (ctx.speculative_outer_type,
kono
parents:
diff changeset
2600 ctx.speculative_offset,
kono
parents:
diff changeset
2601 ctx.speculative_maybe_derived_type,
kono
parents:
diff changeset
2602 otr_type);
kono
parents:
diff changeset
2603
kono
parents:
diff changeset
2604 if (updated && dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2605 {
kono
parents:
diff changeset
2606 fprintf (dump_file, "Updated as: ");
kono
parents:
diff changeset
2607 dump (dump_file);
kono
parents:
diff changeset
2608 fprintf (dump_file, "\n");
kono
parents:
diff changeset
2609 }
kono
parents:
diff changeset
2610 return updated;
kono
parents:
diff changeset
2611 }