]>
Commit | Line | Data |
---|---|---|
c28a7c24 | 1 | /* Subroutines for the C front end on the PowerPC architecture. |
a945c346 | 2 | Copyright (C) 2002-2024 Free Software Foundation, Inc. |
a5c76ee6 ZW |
3 | |
4 | Contributed by Zack Weinberg <zack@codesourcery.com> | |
58646b77 | 5 | and Paolo Bonzini <bonzini@gnu.org> |
a5c76ee6 | 6 | |
5de601cf | 7 | This file is part of GCC. |
a5c76ee6 | 8 | |
5de601cf NC |
9 | GCC is free software; you can redistribute it and/or modify it |
10 | under the terms of the GNU General Public License as published | |
2f83c7d6 | 11 | by the Free Software Foundation; either version 3, or (at your |
5de601cf | 12 | option) any later version. |
a5c76ee6 | 13 | |
5de601cf NC |
14 | GCC is distributed in the hope that it will be useful, but WITHOUT |
15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
16 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
17 | License for more details. | |
a5c76ee6 | 18 | |
5de601cf | 19 | You should have received a copy of the GNU General Public License |
2f83c7d6 NC |
20 | along with GCC; see the file COPYING3. If not see |
21 | <http://www.gnu.org/licenses/>. */ | |
a5c76ee6 | 22 | |
8fcc61f8 RS |
23 | #define IN_TARGET_CODE 1 |
24 | ||
a5c76ee6 ZW |
25 | #include "config.h" |
26 | #include "system.h" | |
4977bab6 | 27 | #include "coretypes.h" |
e11c4407 | 28 | #include "target.h" |
39dabefd | 29 | #include "c-family/c-common.h" |
4d0cdd0c | 30 | #include "memmodel.h" |
a5c76ee6 | 31 | #include "tm_p.h" |
e11c4407 AM |
32 | #include "stringpool.h" |
33 | #include "stor-layout.h" | |
34 | #include "c-family/c-pragma.h" | |
58646b77 | 35 | #include "langhooks.h" |
1c7733a7 | 36 | #include "c/c-tree.h" |
58646b77 | 37 | |
d683a1b3 | 38 | #include "rs6000-internal.h" |
93b5a667 | 39 | |
a5c76ee6 ZW |
40 | /* Handle the machine specific pragma longcall. Its syntax is |
41 | ||
42 | # pragma longcall ( TOGGLE ) | |
43 | ||
44 | where TOGGLE is either 0 or 1. | |
45 | ||
46 | rs6000_default_long_calls is set to the value of TOGGLE, changing | |
47 | whether or not new function declarations receive a longcall | |
48 | attribute by default. */ | |
49 | ||
cb7ac91b ML |
50 | void |
51 | rs6000_pragma_longcall (cpp_reader *pfile ATTRIBUTE_UNUSED) | |
52 | { | |
b9b8dde3 DD |
53 | #define SYNTAX_ERROR(gmsgid) do { \ |
54 | warning (OPT_Wpragmas, gmsgid); \ | |
cb7ac91b | 55 | warning (OPT_Wpragmas, "ignoring malformed %<#pragma longcall%>"); \ |
b9b8dde3 | 56 | return; \ |
a5c76ee6 ZW |
57 | } while (0) |
58 | ||
cb7ac91b ML |
59 | |
60 | ||
a5c76ee6 ZW |
61 | tree x, n; |
62 | ||
63 | /* If we get here, generic code has already scanned the directive | |
64 | leader and the word "longcall". */ | |
65 | ||
75ce3d48 | 66 | if (pragma_lex (&x) != CPP_OPEN_PAREN) |
a5c76ee6 | 67 | SYNTAX_ERROR ("missing open paren"); |
75ce3d48 | 68 | if (pragma_lex (&n) != CPP_NUMBER) |
a5c76ee6 | 69 | SYNTAX_ERROR ("missing number"); |
75ce3d48 | 70 | if (pragma_lex (&x) != CPP_CLOSE_PAREN) |
a5c76ee6 ZW |
71 | SYNTAX_ERROR ("missing close paren"); |
72 | ||
73 | if (n != integer_zero_node && n != integer_one_node) | |
74 | SYNTAX_ERROR ("number must be 0 or 1"); | |
75 | ||
75ce3d48 | 76 | if (pragma_lex (&x) != CPP_EOF) |
cb7ac91b | 77 | warning (OPT_Wpragmas, "junk at end of %<#pragma longcall%>"); |
a5c76ee6 ZW |
78 | |
79 | rs6000_default_long_calls = (n == integer_one_node); | |
80 | } | |
4c4eb375 GK |
81 | |
82 | /* Handle defining many CPP flags based on TARGET_xxx. As a general | |
83 | policy, rather than trying to guess what flags a user might want a | |
84 | #define for, it's better to define a flag for everything. */ | |
85 | ||
86 | #define builtin_define(TXT) cpp_define (pfile, TXT) | |
87 | #define builtin_assert(TXT) cpp_assert (pfile, TXT) | |
88 | ||
5950c3c9 | 89 | /* Keep the AltiVec keywords handy for fast comparisons. */ |
ce26ee21 BE |
90 | static GTY(()) tree __vector_keyword; |
91 | static GTY(()) tree vector_keyword; | |
92 | static GTY(()) tree __pixel_keyword; | |
93 | static GTY(()) tree pixel_keyword; | |
94 | static GTY(()) tree __bool_keyword; | |
95 | static GTY(()) tree bool_keyword; | |
58195b74 | 96 | static GTY(()) tree _Bool_keyword; |
a16a872d MM |
97 | static GTY(()) tree __int128_type; |
98 | static GTY(()) tree __uint128_type; | |
5950c3c9 BE |
99 | |
100 | /* Preserved across calls. */ | |
101 | static tree expand_bool_pixel; | |
102 | ||
103 | static cpp_hashnode * | |
104 | altivec_categorize_keyword (const cpp_token *tok) | |
105 | { | |
106 | if (tok->type == CPP_NAME) | |
107 | { | |
7a2738fa | 108 | cpp_hashnode *ident = tok->val.node.node; |
5950c3c9 | 109 | |
a76ddc7b | 110 | if (ident == C_CPP_HASHNODE (vector_keyword)) |
5950c3c9 BE |
111 | return C_CPP_HASHNODE (__vector_keyword); |
112 | ||
a76ddc7b | 113 | if (ident == C_CPP_HASHNODE (pixel_keyword)) |
5950c3c9 BE |
114 | return C_CPP_HASHNODE (__pixel_keyword); |
115 | ||
a76ddc7b | 116 | if (ident == C_CPP_HASHNODE (bool_keyword)) |
5950c3c9 BE |
117 | return C_CPP_HASHNODE (__bool_keyword); |
118 | ||
58195b74 JJ |
119 | if (ident == C_CPP_HASHNODE (_Bool_keyword)) |
120 | return C_CPP_HASHNODE (__bool_keyword); | |
121 | ||
5950c3c9 BE |
122 | return ident; |
123 | } | |
124 | ||
125 | return 0; | |
126 | } | |
127 | ||
128 | static void | |
129 | init_vector_keywords (void) | |
130 | { | |
a16a872d MM |
131 | /* Keywords without two leading underscores are context-sensitive, and hence |
132 | implemented as conditional macros, controlled by the | |
133 | rs6000_macro_to_expand() function below. If we have ISA 2.07 64-bit | |
134 | support, record the __int128_t and __uint128_t types. */ | |
5950c3c9 BE |
135 | |
136 | __vector_keyword = get_identifier ("__vector"); | |
137 | C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL; | |
138 | ||
139 | __pixel_keyword = get_identifier ("__pixel"); | |
140 | C_CPP_HASHNODE (__pixel_keyword)->flags |= NODE_CONDITIONAL; | |
141 | ||
142 | __bool_keyword = get_identifier ("__bool"); | |
143 | C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL; | |
144 | ||
145 | vector_keyword = get_identifier ("vector"); | |
146 | C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL; | |
147 | ||
148 | pixel_keyword = get_identifier ("pixel"); | |
149 | C_CPP_HASHNODE (pixel_keyword)->flags |= NODE_CONDITIONAL; | |
150 | ||
151 | bool_keyword = get_identifier ("bool"); | |
152 | C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL; | |
58195b74 JJ |
153 | |
154 | _Bool_keyword = get_identifier ("_Bool"); | |
155 | C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL; | |
a16a872d MM |
156 | |
157 | if (TARGET_VADDUQM) | |
158 | { | |
159 | __int128_type = get_identifier ("__int128_t"); | |
160 | __uint128_type = get_identifier ("__uint128_t"); | |
161 | } | |
5950c3c9 BE |
162 | } |
163 | ||
92d0307d DD |
164 | /* Helper function to find out which RID_INT_N_* code is the one for |
165 | __int128, if any. Returns RID_MAX+1 if none apply, which is safe | |
166 | (for our purposes, since we always expect to have __int128) to | |
167 | compare against. */ | |
168 | static int | |
169 | rid_int128(void) | |
170 | { | |
171 | int i; | |
172 | ||
173 | for (i = 0; i < NUM_INT_N_ENTS; i ++) | |
174 | if (int_n_enabled_p[i] | |
175 | && int_n_data[i].bitsize == 128) | |
176 | return RID_INT_N_0 + i; | |
177 | ||
178 | return RID_MAX + 1; | |
179 | } | |
180 | ||
067fe66c JG |
181 | /* Called to decide whether a conditional macro should be expanded |
182 | by peeking two or more tokens(_bool/_pixel/int/long/double/...). */ | |
5950c3c9 BE |
183 | |
184 | static cpp_hashnode * | |
185 | rs6000_macro_to_expand (cpp_reader *pfile, const cpp_token *tok) | |
186 | { | |
7a2738fa | 187 | cpp_hashnode *expand_this = tok->val.node.node; |
5950c3c9 BE |
188 | cpp_hashnode *ident; |
189 | ||
7fa14a01 MM |
190 | /* If the current machine does not have altivec, don't look for the |
191 | keywords. */ | |
192 | if (!TARGET_ALTIVEC) | |
193 | return NULL; | |
194 | ||
5950c3c9 BE |
195 | ident = altivec_categorize_keyword (tok); |
196 | ||
a76ddc7b JJ |
197 | if (ident != expand_this) |
198 | expand_this = NULL; | |
199 | ||
5950c3c9 BE |
200 | if (ident == C_CPP_HASHNODE (__vector_keyword)) |
201 | { | |
a76ddc7b JJ |
202 | int idx = 0; |
203 | do | |
204 | tok = cpp_peek_token (pfile, idx++); | |
205 | while (tok->type == CPP_PADDING); | |
5950c3c9 BE |
206 | ident = altivec_categorize_keyword (tok); |
207 | ||
a76ddc7b | 208 | if (ident == C_CPP_HASHNODE (__pixel_keyword)) |
5950c3c9 BE |
209 | { |
210 | expand_this = C_CPP_HASHNODE (__vector_keyword); | |
211 | expand_bool_pixel = __pixel_keyword; | |
212 | } | |
213 | else if (ident == C_CPP_HASHNODE (__bool_keyword)) | |
214 | { | |
215 | expand_this = C_CPP_HASHNODE (__vector_keyword); | |
216 | expand_bool_pixel = __bool_keyword; | |
217 | } | |
34709a5a MM |
218 | /* The boost libraries have code with Iterator::vector vector in it. If |
219 | we allow the normal handling, this module will be called recursively, | |
220 | and the vector will be skipped.; */ | |
221 | else if (ident && (ident != C_CPP_HASHNODE (__vector_keyword))) | |
5950c3c9 BE |
222 | { |
223 | enum rid rid_code = (enum rid)(ident->rid_code); | |
3f6677f4 NS |
224 | bool is_macro = cpp_macro_p (ident); |
225 | ||
6b366948 JJ |
226 | /* If there is a function-like macro, check if it is going to be |
227 | invoked with or without arguments. Without following ( treat | |
228 | it like non-macro, otherwise the following cpp_get_token eats | |
229 | what should be preserved. */ | |
3f6677f4 | 230 | if (is_macro && cpp_fun_like_macro_p (ident)) |
6b366948 JJ |
231 | { |
232 | int idx2 = idx; | |
233 | do | |
234 | tok = cpp_peek_token (pfile, idx2++); | |
235 | while (tok->type == CPP_PADDING); | |
236 | if (tok->type != CPP_OPEN_PAREN) | |
3f6677f4 | 237 | is_macro = false; |
6b366948 | 238 | } |
3f6677f4 NS |
239 | |
240 | if (is_macro) | |
5950c3c9 | 241 | { |
a76ddc7b JJ |
242 | do |
243 | (void) cpp_get_token (pfile); | |
244 | while (--idx > 0); | |
245 | do | |
246 | tok = cpp_peek_token (pfile, idx++); | |
247 | while (tok->type == CPP_PADDING); | |
5950c3c9 | 248 | ident = altivec_categorize_keyword (tok); |
b3bf8855 JJ |
249 | if (ident == C_CPP_HASHNODE (__pixel_keyword)) |
250 | { | |
251 | expand_this = C_CPP_HASHNODE (__vector_keyword); | |
252 | expand_bool_pixel = __pixel_keyword; | |
253 | rid_code = RID_MAX; | |
254 | } | |
255 | else if (ident == C_CPP_HASHNODE (__bool_keyword)) | |
256 | { | |
257 | expand_this = C_CPP_HASHNODE (__vector_keyword); | |
258 | expand_bool_pixel = __bool_keyword; | |
259 | rid_code = RID_MAX; | |
260 | } | |
261 | else if (ident) | |
5950c3c9 BE |
262 | rid_code = (enum rid)(ident->rid_code); |
263 | } | |
264 | ||
265 | if (rid_code == RID_UNSIGNED || rid_code == RID_LONG | |
266 | || rid_code == RID_SHORT || rid_code == RID_SIGNED | |
267 | || rid_code == RID_INT || rid_code == RID_CHAR | |
29e6733c | 268 | || rid_code == RID_FLOAT |
a16a872d | 269 | || (rid_code == RID_DOUBLE && TARGET_VSX) |
92d0307d | 270 | || (rid_code == rid_int128 () && TARGET_VADDUQM)) |
5950c3c9 BE |
271 | { |
272 | expand_this = C_CPP_HASHNODE (__vector_keyword); | |
273 | /* If the next keyword is bool or pixel, it | |
274 | will need to be expanded as well. */ | |
a76ddc7b JJ |
275 | do |
276 | tok = cpp_peek_token (pfile, idx++); | |
277 | while (tok->type == CPP_PADDING); | |
5950c3c9 BE |
278 | ident = altivec_categorize_keyword (tok); |
279 | ||
a76ddc7b | 280 | if (ident == C_CPP_HASHNODE (__pixel_keyword)) |
5950c3c9 BE |
281 | expand_bool_pixel = __pixel_keyword; |
282 | else if (ident == C_CPP_HASHNODE (__bool_keyword)) | |
283 | expand_bool_pixel = __bool_keyword; | |
067fe66c JG |
284 | |
285 | /* If there are more tokens to check. */ | |
286 | else if (ident) | |
5950c3c9 BE |
287 | { |
288 | /* Try two tokens down, too. */ | |
a76ddc7b JJ |
289 | do |
290 | tok = cpp_peek_token (pfile, idx++); | |
291 | while (tok->type == CPP_PADDING); | |
5950c3c9 | 292 | ident = altivec_categorize_keyword (tok); |
a76ddc7b | 293 | if (ident == C_CPP_HASHNODE (__pixel_keyword)) |
5950c3c9 BE |
294 | expand_bool_pixel = __pixel_keyword; |
295 | else if (ident == C_CPP_HASHNODE (__bool_keyword)) | |
296 | expand_bool_pixel = __bool_keyword; | |
297 | } | |
298 | } | |
a16a872d MM |
299 | |
300 | /* Support vector __int128_t, but we don't need to worry about bool | |
301 | or pixel on this type. */ | |
302 | else if (TARGET_VADDUQM | |
303 | && (ident == C_CPP_HASHNODE (__int128_type) | |
304 | || ident == C_CPP_HASHNODE (__uint128_type))) | |
305 | expand_this = C_CPP_HASHNODE (__vector_keyword); | |
5950c3c9 BE |
306 | } |
307 | } | |
308 | else if (expand_bool_pixel && ident == C_CPP_HASHNODE (__pixel_keyword)) | |
309 | { | |
310 | expand_this = C_CPP_HASHNODE (__pixel_keyword); | |
311 | expand_bool_pixel = 0; | |
312 | } | |
313 | else if (expand_bool_pixel && ident == C_CPP_HASHNODE (__bool_keyword)) | |
314 | { | |
315 | expand_this = C_CPP_HASHNODE (__bool_keyword); | |
316 | expand_bool_pixel = 0; | |
317 | } | |
318 | ||
319 | return expand_this; | |
320 | } | |
321 | ||
7fa14a01 MM |
322 | |
323 | /* Define or undefine a single macro. */ | |
324 | ||
325 | static void | |
326 | rs6000_define_or_undefine_macro (bool define_p, const char *name) | |
327 | { | |
328 | if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET) | |
329 | fprintf (stderr, "#%s %s\n", (define_p) ? "define" : "undef", name); | |
330 | ||
331 | if (define_p) | |
332 | cpp_define (parse_in, name); | |
333 | else | |
334 | cpp_undef (parse_in, name); | |
335 | } | |
336 | ||
337 | /* Define or undefine macros based on the current target. If the user does | |
75841b04 | 338 | #pragma GCC target, we need to adjust the macros dynamically. */ |
7fa14a01 MM |
339 | |
340 | void | |
75841b04 | 341 | rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags) |
7fa14a01 MM |
342 | { |
343 | if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET) | |
b85aed95 | 344 | fprintf (stderr, |
75841b04 | 345 | "rs6000_target_modify_macros (%s, " HOST_WIDE_INT_PRINT_HEX ")\n", |
7fa14a01 | 346 | (define_p) ? "define" : "undef", |
75841b04 | 347 | flags); |
7fa14a01 | 348 | |
2b33460a KN |
349 | /* Each of the flags mentioned below controls whether certain |
350 | preprocessor macros will be automatically defined when | |
351 | preprocessing source files for compilation by this compiler. | |
352 | While most of these flags can be enabled or disabled | |
353 | explicitly by specifying certain command-line options when | |
354 | invoking the compiler, there are also many ways in which these | |
355 | flags are enabled or disabled implicitly, based on compiler | |
356 | defaults, configuration choices, and on the presence of certain | |
357 | related command-line options. Many, but not all, of these | |
e53b6e56 | 358 | implicit behaviors can be found in file "rs6000.cc", the |
2b33460a KN |
359 | rs6000_option_override_internal() function. |
360 | ||
361 | In general, each of the flags may be automatically enabled in | |
362 | any of the following conditions: | |
363 | ||
364 | 1. If no -mcpu target is specified on the command line and no | |
365 | --with-cpu target is specified to the configure command line | |
366 | and the TARGET_DEFAULT macro for this default cpu host | |
367 | includes the flag, and the flag has not been explicitly disabled | |
368 | by command-line options. | |
369 | ||
370 | 2. If the target specified with -mcpu=target on the command line, or | |
371 | in the absence of a -mcpu=target command-line option, if the | |
372 | target specified using --with-cpu=target on the configure | |
373 | command line, is disqualified because the associated binary | |
374 | tools (e.g. the assembler) lack support for the requested cpu, | |
375 | and the TARGET_DEFAULT macro for this default cpu host | |
376 | includes the flag, and the flag has not been explicitly disabled | |
377 | by command-line options. | |
378 | ||
379 | 3. If either of the above two conditions apply except that the | |
380 | TARGET_DEFAULT macro is defined to equal zero, and | |
381 | TARGET_POWERPC64 and | |
382 | a) BYTES_BIG_ENDIAN and the flag to be enabled is either | |
eb2887a1 | 383 | OPTION_MASK_PPC_GFXOPT or MASK_POWERPC64 (flags for "powerpc64" |
2b33460a KN |
384 | target), or |
385 | b) !BYTES_BIG_ENDIAN and the flag to be enabled is either | |
386 | MASK_POWERPC64 or it is one of the flags included in | |
387 | ISA_2_7_MASKS_SERVER (flags for "powerpc64le" target). | |
388 | ||
389 | 4. If a cpu has been requested with a -mcpu=target command-line option | |
390 | and this cpu has not been disqualified due to shortcomings of the | |
391 | binary tools, and the set of flags associated with the requested cpu | |
392 | include the flag to be enabled. See rs6000-cpus.def for macro | |
393 | definitions that represent various ABI standards | |
394 | (e.g. ISA_2_1_MASKS, ISA_3_0_MASKS_SERVER) and for a list of | |
395 | the specific flags that are associated with each of the cpu | |
396 | choices that can be specified as the target of a -mcpu=target | |
700d4cb0 | 397 | compile option, or as the target of a --with-cpu=target |
2b33460a KN |
398 | configure option. Target flags that are specified in either |
399 | of these two ways are considered "implicit" since the flags | |
400 | are not mentioned specifically by name. | |
401 | ||
402 | Additional documentation describing behavior specific to | |
403 | particular flags is provided below, immediately preceding the | |
404 | use of each relevant flag. | |
405 | ||
406 | 5. If there is no -mcpu=target command-line option, and the cpu | |
407 | requested by a --with-cpu=target command-line option has not | |
408 | been disqualified due to shortcomings of the binary tools, and | |
409 | the set of flags associated with the specified target include | |
410 | the flag to be enabled. See the notes immediately above for a | |
411 | summary of the flags associated with particular cpu | |
412 | definitions. */ | |
413 | ||
4d967549 | 414 | /* rs6000_isa_flags based options. */ |
a441dedb | 415 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PPC"); |
4d967549 | 416 | if ((flags & OPTION_MASK_PPC_GPOPT) != 0) |
7fa14a01 | 417 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PPCSQ"); |
4d967549 | 418 | if ((flags & OPTION_MASK_PPC_GFXOPT) != 0) |
7fa14a01 | 419 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PPCGR"); |
4d967549 | 420 | if ((flags & OPTION_MASK_POWERPC64) != 0) |
7fa14a01 | 421 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PPC64"); |
4d967549 | 422 | if ((flags & OPTION_MASK_MFCRF) != 0) |
7fa14a01 | 423 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR4"); |
4d967549 | 424 | if ((flags & OPTION_MASK_POPCNTB) != 0) |
7fa14a01 | 425 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR5"); |
4d967549 | 426 | if ((flags & OPTION_MASK_FPRND) != 0) |
7fa14a01 | 427 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR5X"); |
4d967549 | 428 | if ((flags & OPTION_MASK_CMPB) != 0) |
7fa14a01 | 429 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR6"); |
4d967549 | 430 | if ((flags & OPTION_MASK_POPCNTD) != 0) |
7fa14a01 | 431 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR7"); |
2b33460a | 432 | /* Note that the OPTION_MASK_DIRECT_MOVE flag is automatically |
79c4d73b | 433 | turned on in the following condition: |
db1e5f32 MM |
434 | 1. TARGET_P8_VECTOR is enabled and OPTION_MASK_DIRECT_MOVE is not |
435 | explicitly disabled. | |
79c4d73b KN |
436 | Hereafter, the OPTION_MASK_DIRECT_MOVE flag is considered to |
437 | have been turned on explicitly. | |
438 | Note that the OPTION_MASK_DIRECT_MOVE flag is automatically | |
2b33460a KN |
439 | turned off in any of the following conditions: |
440 | 1. TARGET_HARD_FLOAT, TARGET_ALTIVEC, or TARGET_VSX is explicitly | |
441 | disabled and OPTION_MASK_DIRECT_MOVE was not explicitly | |
442 | enabled. | |
443 | 2. TARGET_VSX is off. */ | |
f62511da MM |
444 | if ((flags & OPTION_MASK_DIRECT_MOVE) != 0) |
445 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR8"); | |
d1f0d376 MM |
446 | if ((flags & OPTION_MASK_MODULO) != 0) |
447 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR9"); | |
5d9d0c94 SB |
448 | if ((flags & OPTION_MASK_POWER10) != 0) |
449 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR10"); | |
dc0f9a74 MM |
450 | if ((flags & OPTION_MASK_POWER11) != 0) |
451 | rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR11"); | |
4d967549 | 452 | if ((flags & OPTION_MASK_SOFT_FLOAT) != 0) |
7fa14a01 | 453 | rs6000_define_or_undefine_macro (define_p, "_SOFT_FLOAT"); |
4d967549 | 454 | if ((flags & OPTION_MASK_RECIP_PRECISION) != 0) |
7fa14a01 | 455 | rs6000_define_or_undefine_macro (define_p, "__RECIP_PRECISION__"); |
2b33460a KN |
456 | /* Note that the OPTION_MASK_ALTIVEC flag is automatically turned on |
457 | in any of the following conditions: | |
427a7384 | 458 | 1. The operating system is Darwin and it is configured for 64 |
2b33460a | 459 | bit. (See darwin_rs6000_override_options.) |
427a7384 | 460 | 2. The operating system is Darwin and the operating system |
2b33460a KN |
461 | version is 10.5 or higher and the user has not explicitly |
462 | disabled ALTIVEC by specifying -mcpu=G3 or -mno-altivec and | |
463 | the compiler is not producing code for integration within the | |
464 | kernel. (See darwin_rs6000_override_options.) | |
465 | Note that the OPTION_MASK_ALTIVEC flag is automatically turned | |
466 | off in any of the following conditions: | |
467 | 1. The operating system does not support saving of AltiVec | |
468 | registers (OS_MISSING_ALTIVEC). | |
469 | 2. If an inner context (as introduced by | |
470 | __attribute__((__target__())) or #pragma GCC target() | |
471 | requests a target that normally enables the | |
472 | OPTION_MASK_ALTIVEC flag but the outer-most "main target" | |
473 | does not support the rs6000_altivec_abi, this flag is | |
474 | turned off for the inner context unless OPTION_MASK_ALTIVEC | |
475 | was explicitly enabled for the inner context. */ | |
4d967549 | 476 | if ((flags & OPTION_MASK_ALTIVEC) != 0) |
7fa14a01 MM |
477 | { |
478 | const char *vec_str = (define_p) ? "__VEC__=10206" : "__VEC__"; | |
479 | rs6000_define_or_undefine_macro (define_p, "__ALTIVEC__"); | |
480 | rs6000_define_or_undefine_macro (define_p, vec_str); | |
481 | ||
482 | /* Define this when supporting context-sensitive keywords. */ | |
483 | if (!flag_iso) | |
484 | rs6000_define_or_undefine_macro (define_p, "__APPLE_ALTIVEC__"); | |
2e7750cb DE |
485 | if (rs6000_aix_extabi) |
486 | rs6000_define_or_undefine_macro (define_p, "__EXTABI__"); | |
7fa14a01 | 487 | } |
79c4d73b KN |
488 | /* Note that the OPTION_MASK_VSX flag is automatically turned on in |
489 | the following conditions: | |
490 | 1. TARGET_P8_VECTOR is explicitly turned on and the OPTION_MASK_VSX | |
491 | was not explicitly turned off. Hereafter, the OPTION_MASK_VSX | |
492 | flag is considered to have been explicitly turned on. | |
493 | Note that the OPTION_MASK_VSX flag is automatically turned off in | |
2b33460a KN |
494 | the following conditions: |
495 | 1. The operating system does not support saving of AltiVec | |
496 | registers (OS_MISSING_ALTIVEC). | |
2c2aa74d | 497 | 2. If the option TARGET_HARD_FLOAT is turned off. Hereafter, the |
11d8d07e SB |
498 | OPTION_MASK_VSX flag is considered to have been turned off |
499 | explicitly. | |
55928937 | 500 | 3. If TARGET_AVOID_XFORM is turned on explicitly at the outermost |
2b33460a KN |
501 | compilation context, or if it is turned on by any means in an |
502 | inner compilation context. Hereafter, the OPTION_MASK_VSX | |
503 | flag is considered to have been turned off explicitly. | |
55928937 | 504 | 4. If TARGET_ALTIVEC was explicitly disabled. Hereafter, the |
2b33460a KN |
505 | OPTION_MASK_VSX flag is considered to have been turned off |
506 | explicitly. | |
55928937 | 507 | 5. If an inner context (as introduced by |
2b33460a KN |
508 | __attribute__((__target__())) or #pragma GCC target() |
509 | requests a target that normally enables the | |
510 | OPTION_MASK_VSX flag but the outer-most "main target" | |
511 | does not support the rs6000_altivec_abi, this flag is | |
512 | turned off for the inner context unless OPTION_MASK_VSX | |
513 | was explicitly enabled for the inner context. */ | |
4d967549 | 514 | if ((flags & OPTION_MASK_VSX) != 0) |
7fa14a01 | 515 | rs6000_define_or_undefine_macro (define_p, "__VSX__"); |
0258b6e4 | 516 | if ((flags & OPTION_MASK_HTM) != 0) |
4c1f41e1 PB |
517 | { |
518 | rs6000_define_or_undefine_macro (define_p, "__HTM__"); | |
519 | /* Tell the user that our HTM insn patterns act as memory barriers. */ | |
520 | rs6000_define_or_undefine_macro (define_p, "__TM_FENCE__"); | |
521 | } | |
2b33460a | 522 | /* Note that the OPTION_MASK_P8_VECTOR flag is automatically turned |
79c4d73b KN |
523 | on in the following conditions: |
524 | 1. TARGET_P9_VECTOR is explicitly turned on and | |
525 | OPTION_MASK_P8_VECTOR is not explicitly turned off. | |
526 | Hereafter, the OPTION_MASK_P8_VECTOR flag is considered to | |
527 | have been turned off explicitly. | |
528 | Note that the OPTION_MASK_P8_VECTOR flag is automatically turned | |
2b33460a KN |
529 | off in the following conditions: |
530 | 1. If any of TARGET_HARD_FLOAT, TARGET_ALTIVEC, or TARGET_VSX | |
531 | were turned off explicitly and OPTION_MASK_P8_VECTOR flag was | |
532 | not turned on explicitly. | |
533 | 2. If TARGET_ALTIVEC is turned off. Hereafter, the | |
534 | OPTION_MASK_P8_VECTOR flag is considered to have been turned off | |
535 | explicitly. | |
79c4d73b KN |
536 | 3. If TARGET_VSX is turned off and OPTION_MASK_P8_VECTOR was not |
537 | explicitly enabled. If TARGET_VSX is explicitly enabled, the | |
538 | OPTION_MASK_P8_VECTOR flag is hereafter also considered to | |
539 | have been turned off explicitly. */ | |
f62511da MM |
540 | if ((flags & OPTION_MASK_P8_VECTOR) != 0) |
541 | rs6000_define_or_undefine_macro (define_p, "__POWER8_VECTOR__"); | |
2b33460a KN |
542 | /* Note that the OPTION_MASK_P9_VECTOR flag is automatically turned |
543 | off in the following conditions: | |
79c4d73b KN |
544 | 1. If TARGET_P8_VECTOR is turned off and OPTION_MASK_P9_VECTOR is |
545 | not turned on explicitly. Hereafter, if OPTION_MASK_P8_VECTOR | |
546 | was turned on explicitly, the OPTION_MASK_P9_VECTOR flag is | |
547 | also considered to have been turned off explicitly. | |
548 | Note that the OPTION_MASK_P9_VECTOR is automatically turned on | |
549 | in the following conditions: | |
db1e5f32 | 550 | 1. If TARGET_P9_MINMAX was turned on explicitly. |
79c4d73b KN |
551 | Hereafter, THE OPTION_MASK_P9_VECTOR flag is considered to |
552 | have been turned on explicitly. */ | |
50181506 KN |
553 | if ((flags & OPTION_MASK_P9_VECTOR) != 0) |
554 | rs6000_define_or_undefine_macro (define_p, "__POWER9_VECTOR__"); | |
2b33460a KN |
555 | /* Note that the OPTION_MASK_QUAD_MEMORY flag is automatically |
556 | turned off in the following conditions: | |
557 | 1. If TARGET_POWERPC64 is turned off. | |
558 | 2. If WORDS_BIG_ENDIAN is false (non-atomic quad memory | |
559 | load/store are disabled on little endian). */ | |
b846c948 MM |
560 | if ((flags & OPTION_MASK_QUAD_MEMORY) != 0) |
561 | rs6000_define_or_undefine_macro (define_p, "__QUAD_MEMORY__"); | |
2b33460a KN |
562 | /* Note that the OPTION_MASK_QUAD_MEMORY_ATOMIC flag is automatically |
563 | turned off in the following conditions: | |
564 | 1. If TARGET_POWERPC64 is turned off. | |
565 | Note that the OPTION_MASK_QUAD_MEMORY_ATOMIC flag is | |
566 | automatically turned on in the following conditions: | |
567 | 1. If TARGET_QUAD_MEMORY and this flag was not explicitly | |
568 | disabled. */ | |
b846c948 MM |
569 | if ((flags & OPTION_MASK_QUAD_MEMORY_ATOMIC) != 0) |
570 | rs6000_define_or_undefine_macro (define_p, "__QUAD_MEMORY_ATOMIC__"); | |
2b33460a KN |
571 | /* Note that the OPTION_MASK_CRYPTO flag is automatically turned off |
572 | in the following conditions: | |
573 | 1. If any of TARGET_HARD_FLOAT or TARGET_ALTIVEC or TARGET_VSX | |
574 | are turned off explicitly and OPTION_MASK_CRYPTO is not turned | |
575 | on explicitly. | |
576 | 2. If TARGET_ALTIVEC is turned off. */ | |
f62511da MM |
577 | if ((flags & OPTION_MASK_CRYPTO) != 0) |
578 | rs6000_define_or_undefine_macro (define_p, "__CRYPTO__"); | |
bbd35101 MM |
579 | if ((flags & OPTION_MASK_FLOAT128_KEYWORD) != 0) |
580 | { | |
581 | rs6000_define_or_undefine_macro (define_p, "__FLOAT128__"); | |
582 | if (define_p) | |
583 | rs6000_define_or_undefine_macro (true, "__float128=__ieee128"); | |
584 | else | |
585 | rs6000_define_or_undefine_macro (false, "__float128"); | |
6f8abf2b JJ |
586 | if (ieee128_float_type_node && define_p) |
587 | rs6000_define_or_undefine_macro (true, "__SIZEOF_FLOAT128__=16"); | |
588 | else | |
589 | rs6000_define_or_undefine_macro (false, "__SIZEOF_FLOAT128__"); | |
bbd35101 MM |
590 | } |
591 | /* OPTION_MASK_FLOAT128_HARDWARE can be turned on if -mcpu=power9 is used or | |
592 | via the target attribute/pragma. */ | |
593 | if ((flags & OPTION_MASK_FLOAT128_HW) != 0) | |
594 | rs6000_define_or_undefine_macro (define_p, "__FLOAT128_HARDWARE__"); | |
7fa14a01 | 595 | |
75841b04 WS |
596 | /* Tell the user if we are targeting CELL. */ |
597 | if (rs6000_cpu == PROCESSOR_CELL) | |
7fa14a01 | 598 | rs6000_define_or_undefine_macro (define_p, "__PPU__"); |
f002c046 PB |
599 | |
600 | /* Tell the user if we support the MMA instructions. */ | |
601 | if ((flags & OPTION_MASK_MMA) != 0) | |
602 | rs6000_define_or_undefine_macro (define_p, "__MMA__"); | |
677b9150 AM |
603 | /* Whether pc-relative code is being generated. */ |
604 | if ((flags & OPTION_MASK_PCREL) != 0) | |
605 | rs6000_define_or_undefine_macro (define_p, "__PCREL__"); | |
3ec3a9fe BS |
606 | /* Tell the user -mrop-protect is in play. */ |
607 | if (rs6000_rop_protect) | |
608 | rs6000_define_or_undefine_macro (define_p, "__ROP_PROTECT__"); | |
ef3bbc69 CL |
609 | /* Tell the user __builtin_set_fpscr_rn now returns the FPSCR fields |
610 | in a double. Originally the built-in returned void. */ | |
611 | if ((flags & OPTION_MASK_SOFT_FLOAT) == 0) | |
612 | rs6000_define_or_undefine_macro (define_p, | |
613 | "__SET_FPSCR_RN_RETURNS_FPSCR__"); | |
7fa14a01 MM |
614 | } |
615 | ||
4c4eb375 | 616 | void |
a2369ed3 | 617 | rs6000_cpu_cpp_builtins (cpp_reader *pfile) |
4c4eb375 | 618 | { |
7fa14a01 | 619 | /* Define all of the common macros. */ |
75841b04 | 620 | rs6000_target_modify_macros (true, rs6000_isa_flags); |
7fa14a01 | 621 | |
7fa14a01 MM |
622 | if (TARGET_FRE) |
623 | builtin_define ("__RECIP__"); | |
624 | if (TARGET_FRES) | |
625 | builtin_define ("__RECIPF__"); | |
626 | if (TARGET_FRSQRTE) | |
627 | builtin_define ("__RSQRTE__"); | |
628 | if (TARGET_FRSQRTES) | |
629 | builtin_define ("__RSQRTEF__"); | |
08213983 | 630 | if (TARGET_FLOAT128_TYPE) |
6f8abf2b | 631 | builtin_define ("__FLOAT128_TYPE__"); |
687e57d7 MM |
632 | if (ibm128_float_type_node) |
633 | builtin_define ("__SIZEOF_IBM128__=16"); | |
634 | if (ieee128_float_type_node) | |
6f8abf2b | 635 | builtin_define ("__SIZEOF_IEEE128__=16"); |
3787ee47 MM |
636 | #ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB |
637 | builtin_define ("__BUILTIN_CPU_SUPPORTS__"); | |
638 | #endif | |
08213983 | 639 | |
860f8be4 | 640 | if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM) |
7fa14a01 | 641 | { |
8bb418a3 ZL |
642 | /* Define the AltiVec syntactic elements. */ |
643 | builtin_define ("__vector=__attribute__((altivec(vector__)))"); | |
644 | builtin_define ("__pixel=__attribute__((altivec(pixel__))) unsigned short"); | |
645 | builtin_define ("__bool=__attribute__((altivec(bool__))) unsigned"); | |
5950c3c9 BE |
646 | |
647 | if (!flag_iso) | |
648 | { | |
5950c3c9 BE |
649 | builtin_define ("vector=vector"); |
650 | builtin_define ("pixel=pixel"); | |
651 | builtin_define ("bool=bool"); | |
58195b74 | 652 | builtin_define ("_Bool=_Bool"); |
5950c3c9 BE |
653 | init_vector_keywords (); |
654 | ||
655 | /* Enable context-sensitive macros. */ | |
656 | cpp_get_callbacks (pfile)->macro_to_expand = rs6000_macro_to_expand; | |
657 | } | |
8bb418a3 | 658 | } |
2c2aa74d | 659 | if (!TARGET_HARD_FLOAT) |
17caeff2 | 660 | builtin_define ("_SOFT_DOUBLE"); |
b4d330e1 DE |
661 | /* Used by lwarx/stwcx. errata work-around. */ |
662 | if (rs6000_cpu == PROCESSOR_PPC405) | |
663 | builtin_define ("__PPC405__"); | |
86098753 JM |
664 | /* Used by libstdc++. */ |
665 | if (TARGET_NO_LWSYNC) | |
666 | builtin_define ("__NO_LWSYNC__"); | |
29e6733c | 667 | |
7fa14a01 MM |
668 | if (TARGET_EXTRA_BUILTINS) |
669 | { | |
29e6733c MM |
670 | /* For the VSX builtin functions identical to Altivec functions, just map |
671 | the altivec builtin into the vsx version (the altivec functions | |
672 | generate VSX code if -mvsx). */ | |
673 | builtin_define ("__builtin_vsx_xxland=__builtin_vec_and"); | |
674 | builtin_define ("__builtin_vsx_xxlandc=__builtin_vec_andc"); | |
675 | builtin_define ("__builtin_vsx_xxlnor=__builtin_vec_nor"); | |
676 | builtin_define ("__builtin_vsx_xxlor=__builtin_vec_or"); | |
677 | builtin_define ("__builtin_vsx_xxlxor=__builtin_vec_xor"); | |
678 | builtin_define ("__builtin_vsx_xxsel=__builtin_vec_sel"); | |
679 | builtin_define ("__builtin_vsx_vperm=__builtin_vec_perm"); | |
680 | ||
681 | /* Also map the a and m versions of the multiply/add instructions to the | |
682 | builtin for people blindly going off the instruction manual. */ | |
683 | builtin_define ("__builtin_vsx_xvmaddadp=__builtin_vsx_xvmadddp"); | |
684 | builtin_define ("__builtin_vsx_xvmaddmdp=__builtin_vsx_xvmadddp"); | |
685 | builtin_define ("__builtin_vsx_xvmaddasp=__builtin_vsx_xvmaddsp"); | |
686 | builtin_define ("__builtin_vsx_xvmaddmsp=__builtin_vsx_xvmaddsp"); | |
687 | builtin_define ("__builtin_vsx_xvmsubadp=__builtin_vsx_xvmsubdp"); | |
688 | builtin_define ("__builtin_vsx_xvmsubmdp=__builtin_vsx_xvmsubdp"); | |
689 | builtin_define ("__builtin_vsx_xvmsubasp=__builtin_vsx_xvmsubsp"); | |
690 | builtin_define ("__builtin_vsx_xvmsubmsp=__builtin_vsx_xvmsubsp"); | |
691 | builtin_define ("__builtin_vsx_xvnmaddadp=__builtin_vsx_xvnmadddp"); | |
692 | builtin_define ("__builtin_vsx_xvnmaddmdp=__builtin_vsx_xvnmadddp"); | |
693 | builtin_define ("__builtin_vsx_xvnmaddasp=__builtin_vsx_xvnmaddsp"); | |
694 | builtin_define ("__builtin_vsx_xvnmaddmsp=__builtin_vsx_xvnmaddsp"); | |
695 | builtin_define ("__builtin_vsx_xvnmsubadp=__builtin_vsx_xvnmsubdp"); | |
696 | builtin_define ("__builtin_vsx_xvnmsubmdp=__builtin_vsx_xvnmsubdp"); | |
697 | builtin_define ("__builtin_vsx_xvnmsubasp=__builtin_vsx_xvnmsubsp"); | |
698 | builtin_define ("__builtin_vsx_xvnmsubmsp=__builtin_vsx_xvnmsubsp"); | |
699 | } | |
700 | ||
ef836167 | 701 | /* Map the old _Float128 'q' builtins into the new 'f128' builtins. */ |
aeed6d61 MM |
702 | if (TARGET_FLOAT128_TYPE) |
703 | { | |
ef836167 MM |
704 | builtin_define ("__builtin_fabsq=__builtin_fabsf128"); |
705 | builtin_define ("__builtin_copysignq=__builtin_copysignf128"); | |
706 | builtin_define ("__builtin_nanq=__builtin_nanf128"); | |
707 | builtin_define ("__builtin_nansq=__builtin_nansf128"); | |
708 | builtin_define ("__builtin_infq=__builtin_inff128"); | |
709 | builtin_define ("__builtin_huge_valq=__builtin_huge_valf128"); | |
aeed6d61 MM |
710 | } |
711 | ||
29e6733c MM |
712 | /* Tell users they can use __builtin_bswap{16,64}. */ |
713 | builtin_define ("__HAVE_BSWAP__"); | |
647d340d JT |
714 | |
715 | /* May be overridden by target configuration. */ | |
716 | RS6000_CPU_CPP_ENDIAN_BUILTINS(); | |
717 | ||
4c4eb375 | 718 | if (TARGET_LONG_DOUBLE_128) |
ba6a1b78 DE |
719 | { |
720 | builtin_define ("__LONG_DOUBLE_128__"); | |
721 | builtin_define ("__LONGDOUBLE128"); | |
bdb60a10 MM |
722 | |
723 | if (TARGET_IEEEQUAD) | |
8c7a27d5 MM |
724 | { |
725 | /* Older versions of GLIBC used __attribute__((__KC__)) to create the | |
726 | IEEE 128-bit floating point complex type for C++ (which does not | |
727 | support _Float128 _Complex). If the default for long double is | |
728 | IEEE 128-bit mode, the library would need to use | |
729 | __attribute__((__TC__)) instead. Defining __KF__ and __KC__ | |
730 | is a stop-gap to build with the older libraries, until we | |
731 | get an updated library. */ | |
732 | builtin_define ("__LONG_DOUBLE_IEEE128__"); | |
733 | builtin_define ("__KF__=__TF__"); | |
734 | builtin_define ("__KC__=__TC__"); | |
735 | } | |
bdb60a10 MM |
736 | else |
737 | builtin_define ("__LONG_DOUBLE_IBM128__"); | |
ba6a1b78 | 738 | } |
4c4eb375 | 739 | |
7f9f095e AM |
740 | switch (TARGET_CMODEL) |
741 | { | |
742 | /* Deliberately omit __CMODEL_SMALL__ since that was the default | |
743 | before --mcmodel support was added. */ | |
744 | case CMODEL_MEDIUM: | |
745 | builtin_define ("__CMODEL_MEDIUM__"); | |
746 | break; | |
747 | case CMODEL_LARGE: | |
748 | builtin_define ("__CMODEL_LARGE__"); | |
749 | break; | |
750 | default: | |
751 | break; | |
752 | } | |
753 | ||
4c4eb375 GK |
754 | switch (rs6000_current_abi) |
755 | { | |
756 | case ABI_V4: | |
757 | builtin_define ("_CALL_SYSV"); | |
758 | break; | |
4c4eb375 GK |
759 | case ABI_AIX: |
760 | builtin_define ("_CALL_AIXDESC"); | |
761 | builtin_define ("_CALL_AIX"); | |
b54214fe UW |
762 | builtin_define ("_CALL_ELF=1"); |
763 | break; | |
764 | case ABI_ELFv2: | |
765 | builtin_define ("_CALL_ELF=2"); | |
4c4eb375 GK |
766 | break; |
767 | case ABI_DARWIN: | |
768 | builtin_define ("_CALL_DARWIN"); | |
769 | break; | |
b4d330e1 DE |
770 | default: |
771 | break; | |
4c4eb375 | 772 | } |
58646b77 | 773 | |
6800aaee | 774 | /* Vector element order. */ |
427a7384 | 775 | if (BYTES_BIG_ENDIAN) |
6800aaee BS |
776 | builtin_define ("__VEC_ELEMENT_REG_ORDER__=__ORDER_BIG_ENDIAN__"); |
777 | else | |
778 | builtin_define ("__VEC_ELEMENT_REG_ORDER__=__ORDER_LITTLE_ENDIAN__"); | |
779 | ||
89f9fe50 | 780 | /* Let the compiled code know if 'f' class registers will not be available. */ |
11d8d07e | 781 | if (TARGET_SOFT_FLOAT) |
89f9fe50 | 782 | builtin_define ("__NO_FPRS__"); |
9eca1774 | 783 | |
b54214fe UW |
784 | /* Whether aggregates passed by value are aligned to a 16 byte boundary |
785 | if their alignment is 16 bytes or larger. */ | |
786 | if ((TARGET_MACHO && rs6000_darwin64_abi) | |
787 | || DEFAULT_ABI == ABI_ELFv2 | |
788 | || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm)) | |
789 | builtin_define ("__STRUCT_PARM_ALIGN__=16"); | |
58646b77 PB |
790 | } |
791 | ||
58646b77 PB |
792 | \f |
793 | ||
794 | /* Convert a type stored into a struct altivec_builtin_types as ID, | |
795 | into a tree. The types are in rs6000_builtin_types: negative values | |
796 | create a pointer type for the type associated to ~ID. Note it is | |
797 | a logical NOT, rather than a negation, otherwise you cannot represent | |
798 | a pointer type for ID 0. */ | |
799 | ||
800 | static inline tree | |
801 | rs6000_builtin_type (int id) | |
802 | { | |
803 | tree t; | |
804 | t = rs6000_builtin_types[id < 0 ? ~id : id]; | |
805 | return id < 0 ? build_pointer_type (t) : t; | |
806 | } | |
807 | ||
cdb4b7aa MM |
808 | /* Check whether the type of an argument, T, is compatible with a type ID |
809 | stored into a struct altivec_builtin_types. Integer types are considered | |
810 | compatible; otherwise, the language hook lang_hooks.types_compatible_p makes | |
811 | the decision. Also allow long double and _Float128 to be compatible if | |
812 | -mabi=ieeelongdouble. */ | |
58646b77 | 813 | |
cdb4b7aa MM |
814 | static inline bool |
815 | is_float128_p (tree t) | |
816 | { | |
817 | return (t == float128_type_node | |
b0420889 | 818 | || (t && t == float128t_type_node) |
cdb4b7aa MM |
819 | || (TARGET_IEEEQUAD |
820 | && TARGET_LONG_DOUBLE_128 | |
821 | && t == long_double_type_node)); | |
822 | } | |
823 | ||
93b5a667 BS |
824 | |
825 | /* Return true iff ARGTYPE can be compatibly passed as PARMTYPE. */ | |
826 | static bool | |
d9421a8d | 827 | rs6000_builtin_type_compatible (tree parmtype, tree argtype) |
93b5a667 BS |
828 | { |
829 | if (parmtype == error_mark_node) | |
830 | return false; | |
831 | ||
832 | if (INTEGRAL_TYPE_P (parmtype) && INTEGRAL_TYPE_P (argtype)) | |
833 | return true; | |
834 | ||
835 | if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 | |
836 | && is_float128_p (parmtype) && is_float128_p (argtype)) | |
837 | return true; | |
838 | ||
839 | if (POINTER_TYPE_P (parmtype) && POINTER_TYPE_P (argtype)) | |
840 | { | |
841 | parmtype = TREE_TYPE (parmtype); | |
842 | argtype = TREE_TYPE (argtype); | |
843 | if (TYPE_READONLY (argtype)) | |
844 | parmtype = build_qualified_type (parmtype, TYPE_QUAL_CONST); | |
845 | } | |
846 | ||
847 | return lang_hooks.types_compatible_p (parmtype, argtype); | |
848 | } | |
849 | ||
24d5b351 BS |
850 | /* In addition to calling fold_convert for EXPR of type TYPE, also |
851 | call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be | |
852 | hiding there (PR47197). */ | |
853 | ||
854 | static tree | |
855 | fully_fold_convert (tree type, tree expr) | |
856 | { | |
857 | tree result = fold_convert (type, expr); | |
858 | bool maybe_const = true; | |
859 | ||
860 | if (!c_dialect_cxx ()) | |
861 | result = c_fully_fold (result, false, &maybe_const); | |
862 | ||
863 | return result; | |
864 | } | |
865 | ||
93b5a667 BS |
866 | /* Build a tree for a function call to an Altivec non-overloaded builtin. |
867 | The overloaded builtin that matched the types and args is described | |
868 | by DESC. The N arguments are given in ARGS, respectively. | |
869 | ||
870 | Actually the only thing it does is calling fold_convert on ARGS, with | |
871 | a small exception for vec_{all,any}_{ge,le} predicates. */ | |
872 | ||
873 | static tree | |
d9421a8d BS |
874 | altivec_build_resolved_builtin (tree *args, int n, tree fntype, tree ret_type, |
875 | rs6000_gen_builtins bif_id, | |
876 | rs6000_gen_builtins ovld_id) | |
93b5a667 BS |
877 | { |
878 | tree argtypes = TYPE_ARG_TYPES (fntype); | |
879 | tree arg_type[MAX_OVLD_ARGS]; | |
926d6490 | 880 | tree fndecl = rs6000_builtin_decls[bif_id]; |
93b5a667 BS |
881 | |
882 | for (int i = 0; i < n; i++) | |
883 | { | |
884 | arg_type[i] = TREE_VALUE (argtypes); | |
885 | argtypes = TREE_CHAIN (argtypes); | |
886 | } | |
887 | ||
888 | /* The AltiVec overloading implementation is overall gross, but this | |
889 | is particularly disgusting. The vec_{all,any}_{ge,le} builtins | |
890 | are completely different for floating-point vs. integer vector | |
891 | types, because the former has vcmpgefp, but the latter should use | |
892 | vcmpgtXX. | |
893 | ||
894 | In practice, the second and third arguments are swapped, and the | |
895 | condition (LT vs. EQ, which is recognizable by bit 1 of the first | |
896 | argument) is reversed. Patch the arguments here before building | |
897 | the resolved CALL_EXPR. */ | |
898 | if (n == 3 | |
899 | && ovld_id == RS6000_OVLD_VEC_CMPGE_P | |
900 | && bif_id != RS6000_BIF_VCMPGEFP_P | |
901 | && bif_id != RS6000_BIF_XVCMPGEDP_P) | |
902 | { | |
903 | std::swap (args[1], args[2]); | |
904 | std::swap (arg_type[1], arg_type[2]); | |
905 | ||
906 | args[0] = fold_build2 (BIT_XOR_EXPR, TREE_TYPE (args[0]), args[0], | |
907 | build_int_cst (NULL_TREE, 2)); | |
908 | } | |
909 | ||
910 | for (int j = 0; j < n; j++) | |
911 | args[j] = fully_fold_convert (arg_type[j], args[j]); | |
912 | ||
913 | /* If the number of arguments to an overloaded function increases, | |
914 | we must expand this switch. */ | |
915 | gcc_assert (MAX_OVLD_ARGS <= 4); | |
916 | ||
917 | tree call; | |
918 | switch (n) | |
919 | { | |
920 | case 0: | |
921 | call = build_call_expr (fndecl, 0); | |
922 | break; | |
923 | case 1: | |
924 | call = build_call_expr (fndecl, 1, args[0]); | |
925 | break; | |
926 | case 2: | |
927 | call = build_call_expr (fndecl, 2, args[0], args[1]); | |
928 | break; | |
929 | case 3: | |
930 | call = build_call_expr (fndecl, 3, args[0], args[1], args[2]); | |
931 | break; | |
932 | case 4: | |
933 | call = build_call_expr (fndecl, 4, args[0], args[1], args[2], args[3]); | |
934 | break; | |
935 | default: | |
936 | gcc_unreachable (); | |
937 | } | |
938 | return fold_convert (ret_type, call); | |
939 | } | |
940 | ||
ab3f5b71 BS |
941 | /* Enumeration of possible results from attempted overload resolution. |
942 | This is used by special-case helper functions to tell their caller | |
943 | whether they succeeded and what still needs to be done. | |
93b5a667 | 944 | |
ab3f5b71 BS |
945 | unresolved = Still needs processing |
946 | resolved = Resolved (but may be an error_mark_node) | |
947 | resolved_bad = An error that needs handling by the caller. */ | |
948 | ||
949 | enum resolution { unresolved, resolved, resolved_bad }; | |
950 | ||
951 | /* Resolve an overloaded vec_mul call and return a tree expression for the | |
b28b92bc BS |
952 | resolved call if successful. ARGS contains the arguments to the call. |
953 | TYPES contains their types. RES must be set to indicate the status of | |
ab3f5b71 BS |
954 | the resolution attempt. LOC contains statement location information. */ |
955 | ||
956 | static tree | |
b28b92bc | 957 | resolve_vec_mul (resolution *res, tree *args, tree *types, location_t loc) |
93b5a667 | 958 | { |
ab3f5b71 BS |
959 | /* vec_mul needs to be special cased because there are no instructions for it |
960 | for the {un}signed char, {un}signed short, and {un}signed int types. */ | |
93b5a667 | 961 | |
ab3f5b71 | 962 | /* Both arguments must be vectors and the types must be compatible. */ |
b28b92bc BS |
963 | if (TREE_CODE (types[0]) != VECTOR_TYPE |
964 | || !lang_hooks.types_compatible_p (types[0], types[1])) | |
ab3f5b71 BS |
965 | { |
966 | *res = resolved_bad; | |
967 | return error_mark_node; | |
968 | } | |
93b5a667 | 969 | |
b28b92bc | 970 | switch (TYPE_MODE (TREE_TYPE (types[0]))) |
ab3f5b71 BS |
971 | { |
972 | case E_QImode: | |
973 | case E_HImode: | |
974 | case E_SImode: | |
975 | case E_DImode: | |
976 | case E_TImode: | |
977 | /* For scalar types just use a multiply expression. */ | |
978 | *res = resolved; | |
b28b92bc BS |
979 | return fold_build2_loc (loc, MULT_EXPR, types[0], args[0], |
980 | fold_convert (types[0], args[1])); | |
ab3f5b71 BS |
981 | case E_SFmode: |
982 | { | |
983 | /* For floats use the xvmulsp instruction directly. */ | |
984 | *res = resolved; | |
985 | tree call = rs6000_builtin_decls[RS6000_BIF_XVMULSP]; | |
b28b92bc | 986 | return build_call_expr (call, 2, args[0], args[1]); |
ab3f5b71 BS |
987 | } |
988 | case E_DFmode: | |
989 | { | |
990 | /* For doubles use the xvmuldp instruction directly. */ | |
991 | *res = resolved; | |
992 | tree call = rs6000_builtin_decls[RS6000_BIF_XVMULDP]; | |
b28b92bc | 993 | return build_call_expr (call, 2, args[0], args[1]); |
ab3f5b71 BS |
994 | } |
995 | /* Other types are errors. */ | |
996 | default: | |
997 | *res = resolved_bad; | |
998 | return error_mark_node; | |
999 | } | |
1000 | } | |
93b5a667 | 1001 | |
ab3f5b71 | 1002 | /* Resolve an overloaded vec_cmpne call and return a tree expression for the |
b28b92bc BS |
1003 | resolved call if successful. ARGS contains the arguments to the call. |
1004 | TYPES contains their types. RES must be set to indicate the status of | |
ab3f5b71 | 1005 | the resolution attempt. LOC contains statement location information. */ |
93b5a667 | 1006 | |
ab3f5b71 | 1007 | static tree |
b28b92bc | 1008 | resolve_vec_cmpne (resolution *res, tree *args, tree *types, location_t loc) |
ab3f5b71 BS |
1009 | { |
1010 | /* vec_cmpne needs to be special cased because there are no instructions | |
1011 | for it (prior to power 9). */ | |
93b5a667 | 1012 | |
ab3f5b71 | 1013 | /* Both arguments must be vectors and the types must be compatible. */ |
b28b92bc BS |
1014 | if (TREE_CODE (types[0]) != VECTOR_TYPE |
1015 | || !lang_hooks.types_compatible_p (types[0], types[1])) | |
ab3f5b71 BS |
1016 | { |
1017 | *res = resolved_bad; | |
1018 | return error_mark_node; | |
1019 | } | |
93b5a667 | 1020 | |
b28b92bc | 1021 | machine_mode arg0_elt_mode = TYPE_MODE (TREE_TYPE (types[0])); |
93b5a667 | 1022 | |
ab3f5b71 BS |
1023 | /* Power9 instructions provide the most efficient implementation of |
1024 | ALTIVEC_BUILTIN_VEC_CMPNE if the mode is not DImode or TImode | |
1025 | or SFmode or DFmode. */ | |
1026 | if (!TARGET_P9_VECTOR | |
1027 | || arg0_elt_mode == DImode | |
1028 | || arg0_elt_mode == TImode | |
1029 | || arg0_elt_mode == SFmode | |
1030 | || arg0_elt_mode == DFmode) | |
1031 | { | |
1032 | switch (arg0_elt_mode) | |
93b5a667 | 1033 | { |
ab3f5b71 BS |
1034 | /* vec_cmpneq (va, vb) == vec_nor (vec_cmpeq (va, vb), |
1035 | vec_cmpeq (va, vb)). */ | |
1036 | /* Note: vec_nand also works but opt changes vec_nand's | |
1037 | to vec_nor's anyway. */ | |
1038 | case E_QImode: | |
1039 | case E_HImode: | |
1040 | case E_SImode: | |
1041 | case E_DImode: | |
1042 | case E_TImode: | |
1043 | case E_SFmode: | |
1044 | case E_DFmode: | |
1045 | { | |
1046 | /* call = vec_cmpeq (va, vb) | |
1047 | result = vec_nor (call, call). */ | |
1048 | vec<tree, va_gc> *params = make_tree_vector (); | |
b28b92bc BS |
1049 | vec_safe_push (params, args[0]); |
1050 | vec_safe_push (params, args[1]); | |
ab3f5b71 BS |
1051 | tree decl = rs6000_builtin_decls[RS6000_OVLD_VEC_CMPEQ]; |
1052 | tree call = altivec_resolve_overloaded_builtin (loc, decl, params); | |
1053 | /* Use save_expr to ensure that operands used more than once | |
1054 | that may have side effects (like calls) are only evaluated | |
1055 | once. */ | |
1056 | call = save_expr (call); | |
1057 | params = make_tree_vector (); | |
1058 | vec_safe_push (params, call); | |
1059 | vec_safe_push (params, call); | |
1060 | decl = rs6000_builtin_decls[RS6000_OVLD_VEC_NOR]; | |
1061 | *res = resolved; | |
1062 | return altivec_resolve_overloaded_builtin (loc, decl, params); | |
1063 | } | |
93b5a667 | 1064 | /* Other types are errors. */ |
ab3f5b71 BS |
1065 | default: |
1066 | *res = resolved_bad; | |
1067 | return error_mark_node; | |
93b5a667 BS |
1068 | } |
1069 | } | |
1070 | ||
ab3f5b71 BS |
1071 | /* Otherwise this call is unresolved, and altivec_resolve_overloaded_builtin |
1072 | will later process the Power9 alternative. */ | |
1073 | *res = unresolved; | |
1074 | return error_mark_node; | |
1075 | } | |
1076 | ||
b28b92bc BS |
1077 | /* Resolve an overloaded vec_adde or vec_sube call and return a tree expression |
1078 | for the resolved call if successful. ARGS contains the arguments to the | |
1079 | call. TYPES contains their arguments. RES must be set to indicate the | |
1080 | status of the resolution attempt. LOC contains statement location | |
1081 | information. */ | |
ab3f5b71 BS |
1082 | |
1083 | static tree | |
1084 | resolve_vec_adde_sube (resolution *res, rs6000_gen_builtins fcode, | |
b28b92bc | 1085 | tree *args, tree *types, location_t loc) |
ab3f5b71 BS |
1086 | { |
1087 | /* vec_adde needs to be special cased because there is no instruction | |
1088 | for the {un}signed int version. */ | |
ab3f5b71 BS |
1089 | |
1090 | /* All 3 arguments must be vectors of (signed or unsigned) (int or | |
1091 | __int128) and the types must be compatible. */ | |
b28b92bc BS |
1092 | if (TREE_CODE (types[0]) != VECTOR_TYPE |
1093 | || !lang_hooks.types_compatible_p (types[0], types[1]) | |
1094 | || !lang_hooks.types_compatible_p (types[1], types[2])) | |
ab3f5b71 BS |
1095 | { |
1096 | *res = resolved_bad; | |
1097 | return error_mark_node; | |
93b5a667 BS |
1098 | } |
1099 | ||
b28b92bc | 1100 | switch (TYPE_MODE (TREE_TYPE (types[0]))) |
93b5a667 | 1101 | { |
ab3f5b71 BS |
1102 | /* For {un}signed ints, |
1103 | vec_adde (va, vb, carryv) == vec_add (vec_add (va, vb), | |
1104 | vec_and (carryv, 1)). | |
1105 | vec_sube (va, vb, carryv) == vec_sub (vec_sub (va, vb), | |
1106 | vec_and (carryv, 1)). */ | |
1107 | case E_SImode: | |
1108 | { | |
1109 | vec<tree, va_gc> *params = make_tree_vector (); | |
b28b92bc BS |
1110 | vec_safe_push (params, args[0]); |
1111 | vec_safe_push (params, args[1]); | |
93b5a667 | 1112 | |
ab3f5b71 BS |
1113 | tree add_sub_builtin; |
1114 | if (fcode == RS6000_OVLD_VEC_ADDE) | |
1115 | add_sub_builtin = rs6000_builtin_decls[RS6000_OVLD_VEC_ADD]; | |
1116 | else | |
1117 | add_sub_builtin = rs6000_builtin_decls[RS6000_OVLD_VEC_SUB]; | |
93b5a667 | 1118 | |
ab3f5b71 BS |
1119 | tree call = altivec_resolve_overloaded_builtin (loc, add_sub_builtin, |
1120 | params); | |
b28b92bc BS |
1121 | tree const1 = build_int_cstu (TREE_TYPE (types[0]), 1); |
1122 | tree ones_vector = build_vector_from_val (types[0], const1); | |
1123 | tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR, types[0], | |
1124 | args[2], ones_vector); | |
ab3f5b71 BS |
1125 | params = make_tree_vector (); |
1126 | vec_safe_push (params, call); | |
1127 | vec_safe_push (params, and_expr); | |
1128 | *res = resolved; | |
1129 | return altivec_resolve_overloaded_builtin (loc, add_sub_builtin, | |
1130 | params); | |
1131 | } | |
1132 | /* For {un}signed __int128s use the vaddeuqm/vsubeuqm instruction | |
1133 | directly using the standard machinery. */ | |
1134 | case E_TImode: | |
1135 | *res = unresolved; | |
1136 | break; | |
93b5a667 | 1137 | |
ab3f5b71 BS |
1138 | /* Types other than {un}signed int and {un}signed __int128 |
1139 | are errors. */ | |
1140 | default: | |
1141 | *res = resolved_bad; | |
93b5a667 BS |
1142 | } |
1143 | ||
ab3f5b71 BS |
1144 | return error_mark_node; |
1145 | } | |
1146 | ||
1147 | /* Resolve an overloaded vec_addec or vec_subec call and return a tree | |
b28b92bc BS |
1148 | expression for the resolved call if successful. ARGS contains the arguments |
1149 | to the call. TYPES contains their types. RES must be set to indicate the | |
1150 | status of the resolution attempt. LOC contains statement location | |
1151 | information. */ | |
ab3f5b71 BS |
1152 | |
1153 | static tree | |
1154 | resolve_vec_addec_subec (resolution *res, rs6000_gen_builtins fcode, | |
b28b92bc | 1155 | tree *args, tree *types, location_t loc) |
ab3f5b71 BS |
1156 | { |
1157 | /* vec_addec and vec_subec needs to be special cased because there is | |
1158 | no instruction for the (un)signed int version. */ | |
ab3f5b71 BS |
1159 | |
1160 | /* All 3 arguments must be vectors of (signed or unsigned) (int or | |
1161 | __int128) and the types must be compatible. */ | |
b28b92bc BS |
1162 | if (TREE_CODE (types[0]) != VECTOR_TYPE |
1163 | || !lang_hooks.types_compatible_p (types[0], types[1]) | |
1164 | || !lang_hooks.types_compatible_p (types[1], types[2])) | |
ab3f5b71 BS |
1165 | { |
1166 | *res = resolved_bad; | |
1167 | return error_mark_node; | |
1168 | } | |
93b5a667 | 1169 | |
b28b92bc | 1170 | switch (TYPE_MODE (TREE_TYPE (types[0]))) |
ab3f5b71 BS |
1171 | { |
1172 | /* For {un}signed ints, | |
1173 | vec_addec (va, vb, carryv) == | |
1174 | vec_or (vec_addc (va, vb), | |
1175 | vec_addc (vec_add (va, vb), | |
1176 | vec_and (carryv, 0x1))). */ | |
1177 | case E_SImode: | |
1178 | { | |
1179 | /* Use save_expr to ensure that operands used more than once that may | |
1180 | have side effects (like calls) are only evaluated once. */ | |
b28b92bc BS |
1181 | args[0] = save_expr (args[0]); |
1182 | args[1] = save_expr (args[1]); | |
ab3f5b71 | 1183 | vec<tree, va_gc> *params = make_tree_vector (); |
b28b92bc BS |
1184 | vec_safe_push (params, args[0]); |
1185 | vec_safe_push (params, args[1]); | |
ab3f5b71 BS |
1186 | |
1187 | tree as_c_builtin; | |
1188 | if (fcode == RS6000_OVLD_VEC_ADDEC) | |
1189 | as_c_builtin = rs6000_builtin_decls[RS6000_OVLD_VEC_ADDC]; | |
1190 | else | |
1191 | as_c_builtin = rs6000_builtin_decls[RS6000_OVLD_VEC_SUBC]; | |
93b5a667 | 1192 | |
ab3f5b71 BS |
1193 | tree call1 = altivec_resolve_overloaded_builtin (loc, as_c_builtin, |
1194 | params); | |
1195 | params = make_tree_vector (); | |
b28b92bc BS |
1196 | vec_safe_push (params, args[0]); |
1197 | vec_safe_push (params, args[1]); | |
93b5a667 | 1198 | |
ab3f5b71 BS |
1199 | tree as_builtin; |
1200 | if (fcode == RS6000_OVLD_VEC_ADDEC) | |
1201 | as_builtin = rs6000_builtin_decls[RS6000_OVLD_VEC_ADD]; | |
1202 | else | |
1203 | as_builtin = rs6000_builtin_decls[RS6000_OVLD_VEC_SUB]; | |
93b5a667 | 1204 | |
ab3f5b71 BS |
1205 | tree call2 = altivec_resolve_overloaded_builtin (loc, as_builtin, |
1206 | params); | |
b28b92bc BS |
1207 | tree const1 = build_int_cstu (TREE_TYPE (types[0]), 1); |
1208 | tree ones_vector = build_vector_from_val (types[0], const1); | |
1209 | tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR, types[0], | |
1210 | args[2], ones_vector); | |
ab3f5b71 BS |
1211 | params = make_tree_vector (); |
1212 | vec_safe_push (params, call2); | |
1213 | vec_safe_push (params, and_expr); | |
1214 | call2 = altivec_resolve_overloaded_builtin (loc, as_c_builtin, params); | |
1215 | params = make_tree_vector (); | |
1216 | vec_safe_push (params, call1); | |
1217 | vec_safe_push (params, call2); | |
1218 | tree or_builtin = rs6000_builtin_decls[RS6000_OVLD_VEC_OR]; | |
1219 | *res = resolved; | |
1220 | return altivec_resolve_overloaded_builtin (loc, or_builtin, params); | |
1221 | } | |
1222 | /* For {un}signed __int128s use the vaddecuq/vsubbecuq | |
1223 | instructions. This occurs through normal processing. */ | |
1224 | case E_TImode: | |
1225 | *res = unresolved; | |
1226 | break; | |
1227 | ||
1228 | /* Types other than {un}signed int and {un}signed __int128 | |
1229 | are errors. */ | |
1230 | default: | |
1231 | *res = resolved_bad; | |
93b5a667 BS |
1232 | } |
1233 | ||
ab3f5b71 BS |
1234 | return error_mark_node; |
1235 | } | |
93b5a667 | 1236 | |
ab3f5b71 BS |
1237 | /* Resolve an overloaded vec_splats or vec_promote call and return a tree |
1238 | expression for the resolved call if successful. NARGS is the number of | |
1239 | arguments to the call. ARGLIST contains the arguments. RES must be set | |
1240 | to indicate the status of the resolution attempt. */ | |
1241 | ||
1242 | static tree | |
1243 | resolve_vec_splats (resolution *res, rs6000_gen_builtins fcode, | |
1244 | vec<tree, va_gc> *arglist, unsigned nargs) | |
1245 | { | |
1246 | const char *name; | |
1247 | name = fcode == RS6000_OVLD_VEC_SPLATS ? "vec_splats" : "vec_promote"; | |
1248 | ||
1249 | if (fcode == RS6000_OVLD_VEC_SPLATS && nargs != 1) | |
1250 | { | |
1251 | error ("builtin %qs only accepts 1 argument", name); | |
1252 | *res = resolved; | |
1253 | return error_mark_node; | |
93b5a667 BS |
1254 | } |
1255 | ||
ab3f5b71 | 1256 | if (fcode == RS6000_OVLD_VEC_PROMOTE && nargs != 2) |
93b5a667 | 1257 | { |
ab3f5b71 BS |
1258 | error ("builtin %qs only accepts 2 arguments", name); |
1259 | *res = resolved; | |
1260 | return error_mark_node; | |
1261 | } | |
93b5a667 | 1262 | |
ab3f5b71 BS |
1263 | /* Ignore promote's element argument. */ |
1264 | if (fcode == RS6000_OVLD_VEC_PROMOTE | |
1265 | && !INTEGRAL_TYPE_P (TREE_TYPE ((*arglist)[1]))) | |
1266 | { | |
1267 | *res = resolved_bad; | |
1268 | return error_mark_node; | |
1269 | } | |
93b5a667 | 1270 | |
ab3f5b71 BS |
1271 | tree arg = (*arglist)[0]; |
1272 | tree type = TREE_TYPE (arg); | |
93b5a667 | 1273 | |
ab3f5b71 BS |
1274 | if (!SCALAR_FLOAT_TYPE_P (type) && !INTEGRAL_TYPE_P (type)) |
1275 | { | |
1276 | *res = resolved_bad; | |
1277 | return error_mark_node; | |
1278 | } | |
93b5a667 | 1279 | |
ab3f5b71 BS |
1280 | bool unsigned_p = TYPE_UNSIGNED (type); |
1281 | int size; | |
93b5a667 | 1282 | |
ab3f5b71 BS |
1283 | switch (TYPE_MODE (type)) |
1284 | { | |
1285 | case E_TImode: | |
1286 | type = unsigned_p ? unsigned_V1TI_type_node : V1TI_type_node; | |
1287 | size = 1; | |
1288 | break; | |
1289 | case E_DImode: | |
1290 | type = unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node; | |
1291 | size = 2; | |
1292 | break; | |
1293 | case E_SImode: | |
1294 | type = unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node; | |
1295 | size = 4; | |
1296 | break; | |
1297 | case E_HImode: | |
1298 | type = unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node; | |
1299 | size = 8; | |
1300 | break; | |
1301 | case E_QImode: | |
1302 | type = unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node; | |
1303 | size = 16; | |
1304 | break; | |
1305 | case E_SFmode: | |
1306 | type = V4SF_type_node; | |
1307 | size = 4; | |
1308 | break; | |
1309 | case E_DFmode: | |
1310 | type = V2DF_type_node; | |
1311 | size = 2; | |
1312 | break; | |
1313 | default: | |
1314 | *res = resolved_bad; | |
1315 | return error_mark_node; | |
1316 | } | |
93b5a667 | 1317 | |
ab3f5b71 BS |
1318 | arg = save_expr (fold_convert (TREE_TYPE (type), arg)); |
1319 | vec<constructor_elt, va_gc> *vec; | |
1320 | vec_alloc (vec, size); | |
93b5a667 | 1321 | |
ab3f5b71 BS |
1322 | for (int i = 0; i < size; i++) |
1323 | { | |
1324 | constructor_elt elt = {NULL_TREE, arg}; | |
1325 | vec->quick_push (elt); | |
1326 | } | |
93b5a667 | 1327 | |
ab3f5b71 BS |
1328 | *res = resolved; |
1329 | return build_constructor (type, vec); | |
1330 | } | |
93b5a667 | 1331 | |
ab3f5b71 BS |
1332 | /* Resolve an overloaded vec_extract call and return a tree expression for |
1333 | the resolved call if successful. NARGS is the number of arguments to | |
1334 | the call. ARGLIST contains the arguments. RES must be set to indicate | |
1335 | the status of the resolution attempt. LOC contains statement location | |
1336 | information. */ | |
93b5a667 | 1337 | |
ab3f5b71 BS |
1338 | static tree |
1339 | resolve_vec_extract (resolution *res, vec<tree, va_gc> *arglist, | |
1340 | unsigned nargs, location_t loc) | |
1341 | { | |
1342 | if (nargs != 2) | |
1343 | { | |
1344 | error ("builtin %qs only accepts 2 arguments", "vec_extract"); | |
1345 | *res = resolved; | |
1346 | return error_mark_node; | |
1347 | } | |
93b5a667 | 1348 | |
ab3f5b71 BS |
1349 | tree arg1 = (*arglist)[0]; |
1350 | tree arg1_type = TREE_TYPE (arg1); | |
1351 | tree arg2 = (*arglist)[1]; | |
93b5a667 | 1352 | |
ab3f5b71 BS |
1353 | if (TREE_CODE (arg1_type) != VECTOR_TYPE |
1354 | || !INTEGRAL_TYPE_P (TREE_TYPE (arg2))) | |
1355 | { | |
1356 | *res = resolved_bad; | |
1357 | return error_mark_node; | |
1358 | } | |
93b5a667 | 1359 | |
ab3f5b71 BS |
1360 | /* See if we can optimize vec_extract with the current VSX instruction |
1361 | set. */ | |
1362 | machine_mode mode = TYPE_MODE (arg1_type); | |
1363 | tree arg1_inner_type; | |
93b5a667 | 1364 | |
ab3f5b71 BS |
1365 | if (VECTOR_MEM_VSX_P (mode)) |
1366 | { | |
1367 | tree call = NULL_TREE; | |
1368 | int nunits = GET_MODE_NUNITS (mode); | |
1369 | arg2 = fold_for_warn (arg2); | |
1370 | ||
1371 | /* If the second argument is an integer constant, generate | |
1372 | the built-in code if we can. We need 64-bit and direct | |
1373 | move to extract the small integer vectors. */ | |
1374 | if (TREE_CODE (arg2) == INTEGER_CST) | |
1375 | { | |
1376 | wide_int selector = wi::to_wide (arg2); | |
1377 | selector = wi::umod_trunc (selector, nunits); | |
1378 | arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector); | |
1379 | switch (mode) | |
93b5a667 | 1380 | { |
ab3f5b71 BS |
1381 | case E_V1TImode: |
1382 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V1TI]; | |
1383 | break; | |
93b5a667 | 1384 | |
ab3f5b71 BS |
1385 | case E_V2DFmode: |
1386 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V2DF]; | |
1387 | break; | |
93b5a667 | 1388 | |
ab3f5b71 BS |
1389 | case E_V2DImode: |
1390 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V2DI]; | |
1391 | break; | |
93b5a667 | 1392 | |
ab3f5b71 BS |
1393 | case E_V4SFmode: |
1394 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V4SF]; | |
1395 | break; | |
93b5a667 | 1396 | |
ab3f5b71 BS |
1397 | case E_V4SImode: |
1398 | if (TARGET_DIRECT_MOVE_64BIT) | |
1399 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V4SI]; | |
1400 | break; | |
93b5a667 | 1401 | |
ab3f5b71 BS |
1402 | case E_V8HImode: |
1403 | if (TARGET_DIRECT_MOVE_64BIT) | |
1404 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V8HI]; | |
1405 | break; | |
93b5a667 | 1406 | |
ab3f5b71 BS |
1407 | case E_V16QImode: |
1408 | if (TARGET_DIRECT_MOVE_64BIT) | |
1409 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V16QI]; | |
1410 | break; | |
1411 | ||
1412 | default: | |
1413 | break; | |
93b5a667 | 1414 | } |
ab3f5b71 | 1415 | } |
93b5a667 | 1416 | |
ab3f5b71 BS |
1417 | /* If the second argument is variable, we can optimize it if we are |
1418 | generating 64-bit code on a machine with direct move. */ | |
1419 | else if (TREE_CODE (arg2) != INTEGER_CST && TARGET_DIRECT_MOVE_64BIT) | |
1420 | { | |
1421 | switch (mode) | |
93b5a667 | 1422 | { |
ab3f5b71 BS |
1423 | case E_V2DFmode: |
1424 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V2DF]; | |
1425 | break; | |
1426 | ||
1427 | case E_V2DImode: | |
1428 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V2DI]; | |
1429 | break; | |
1430 | ||
1431 | case E_V4SFmode: | |
1432 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V4SF]; | |
1433 | break; | |
1434 | ||
1435 | case E_V4SImode: | |
1436 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V4SI]; | |
1437 | break; | |
1438 | ||
1439 | case E_V8HImode: | |
1440 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V8HI]; | |
1441 | break; | |
1442 | ||
1443 | case E_V16QImode: | |
1444 | call = rs6000_builtin_decls[RS6000_BIF_VEC_EXT_V16QI]; | |
1445 | break; | |
1446 | ||
1447 | default: | |
1448 | break; | |
93b5a667 BS |
1449 | } |
1450 | } | |
1451 | ||
ab3f5b71 | 1452 | if (call) |
93b5a667 | 1453 | { |
ab3f5b71 BS |
1454 | tree result = build_call_expr (call, 2, arg1, arg2); |
1455 | /* Coerce the result to vector element type. May be no-op. */ | |
1456 | arg1_inner_type = TREE_TYPE (arg1_type); | |
1457 | result = fold_convert (arg1_inner_type, result); | |
1458 | *res = resolved; | |
1459 | return result; | |
93b5a667 | 1460 | } |
ab3f5b71 BS |
1461 | } |
1462 | ||
1463 | /* Build *(((arg1_inner_type*) & (vector type){arg1}) + arg2). */ | |
1464 | arg1_inner_type = TREE_TYPE (arg1_type); | |
1465 | tree subp = build_int_cst (TREE_TYPE (arg2), | |
1466 | TYPE_VECTOR_SUBPARTS (arg1_type) - 1); | |
1467 | arg2 = build_binary_op (loc, BIT_AND_EXPR, arg2, subp, 0); | |
1468 | ||
1469 | tree decl = build_decl (loc, VAR_DECL, NULL_TREE, arg1_type); | |
1470 | DECL_EXTERNAL (decl) = 0; | |
1471 | TREE_PUBLIC (decl) = 0; | |
1472 | DECL_CONTEXT (decl) = current_function_decl; | |
1473 | TREE_USED (decl) = 1; | |
1474 | TREE_TYPE (decl) = arg1_type; | |
1475 | TREE_READONLY (decl) = TYPE_READONLY (arg1_type); | |
1476 | ||
1477 | tree stmt; | |
1478 | if (c_dialect_cxx ()) | |
1479 | { | |
1480 | stmt = build4 (TARGET_EXPR, arg1_type, decl, arg1, NULL_TREE, NULL_TREE); | |
1481 | SET_EXPR_LOCATION (stmt, loc); | |
1482 | } | |
1483 | else | |
1484 | { | |
1485 | DECL_INITIAL (decl) = arg1; | |
1486 | stmt = build1 (DECL_EXPR, arg1_type, decl); | |
1487 | TREE_ADDRESSABLE (decl) = 1; | |
1488 | SET_EXPR_LOCATION (stmt, loc); | |
1489 | stmt = build1 (COMPOUND_LITERAL_EXPR, arg1_type, stmt); | |
1490 | } | |
1491 | ||
1492 | tree innerptrtype = build_pointer_type (arg1_inner_type); | |
1493 | stmt = build_unary_op (loc, ADDR_EXPR, stmt, 0); | |
1494 | stmt = convert (innerptrtype, stmt); | |
1495 | stmt = build_binary_op (loc, PLUS_EXPR, stmt, arg2, 1); | |
1496 | stmt = build_indirect_ref (loc, stmt, RO_NULL); | |
1497 | ||
1498 | /* PR83660: We mark this as having side effects so that downstream in | |
1499 | fold_build_cleanup_point_expr () it will get a CLEANUP_POINT_EXPR. If it | |
1500 | does not we can run into an ICE later in gimplify_cleanup_point_expr (). | |
1501 | Potentially this causes missed optimization because there actually is no | |
1502 | side effect. */ | |
1503 | if (c_dialect_cxx ()) | |
1504 | TREE_SIDE_EFFECTS (stmt) = 1; | |
1505 | ||
1506 | *res = resolved; | |
1507 | return stmt; | |
1508 | } | |
1509 | ||
1510 | /* Resolve an overloaded vec_insert call and return a tree expression for | |
1511 | the resolved call if successful. NARGS is the number of arguments to | |
1512 | the call. ARGLIST contains the arguments. RES must be set to indicate | |
1513 | the status of the resolution attempt. LOC contains statement location | |
1514 | information. */ | |
1515 | ||
1516 | static tree | |
1517 | resolve_vec_insert (resolution *res, vec<tree, va_gc> *arglist, | |
1518 | unsigned nargs, location_t loc) | |
1519 | { | |
1520 | if (nargs != 3) | |
1521 | { | |
1522 | error ("builtin %qs only accepts 3 arguments", "vec_insert"); | |
1523 | *res = resolved; | |
1524 | return error_mark_node; | |
1525 | } | |
1526 | ||
1527 | tree arg0 = (*arglist)[0]; | |
1528 | tree arg1 = (*arglist)[1]; | |
1529 | tree arg1_type = TREE_TYPE (arg1); | |
1530 | tree arg2 = fold_for_warn ((*arglist)[2]); | |
1531 | ||
1532 | if (TREE_CODE (arg1_type) != VECTOR_TYPE | |
1533 | || !INTEGRAL_TYPE_P (TREE_TYPE (arg2))) | |
1534 | { | |
1535 | *res = resolved_bad; | |
1536 | return error_mark_node; | |
1537 | } | |
1538 | ||
1539 | /* If we can use the VSX xxpermdi instruction, use that for insert. */ | |
1540 | machine_mode mode = TYPE_MODE (arg1_type); | |
1541 | ||
1542 | if ((mode == V2DFmode || mode == V2DImode) | |
1543 | && VECTOR_UNIT_VSX_P (mode) | |
1544 | && TREE_CODE (arg2) == INTEGER_CST) | |
1545 | { | |
1546 | wide_int selector = wi::to_wide (arg2); | |
1547 | selector = wi::umod_trunc (selector, 2); | |
1548 | arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector); | |
1549 | ||
1550 | tree call = NULL_TREE; | |
1551 | if (mode == V2DFmode) | |
1552 | call = rs6000_builtin_decls[RS6000_BIF_VEC_SET_V2DF]; | |
1553 | else if (mode == V2DImode) | |
1554 | call = rs6000_builtin_decls[RS6000_BIF_VEC_SET_V2DI]; | |
1555 | ||
1556 | /* Note, __builtin_vec_insert_<xxx> has vector and scalar types | |
1557 | reversed. */ | |
1558 | if (call) | |
93b5a667 | 1559 | { |
ab3f5b71 BS |
1560 | *res = resolved; |
1561 | return build_call_expr (call, 3, arg1, arg0, arg2); | |
93b5a667 | 1562 | } |
ab3f5b71 | 1563 | } |
93b5a667 | 1564 | |
ab3f5b71 BS |
1565 | else if (mode == V1TImode |
1566 | && VECTOR_UNIT_VSX_P (mode) | |
1567 | && TREE_CODE (arg2) == INTEGER_CST) | |
1568 | { | |
1569 | tree call = rs6000_builtin_decls[RS6000_BIF_VEC_SET_V1TI]; | |
1570 | wide_int selector = wi::zero(32); | |
1571 | arg2 = wide_int_to_tree (TREE_TYPE (arg2), selector); | |
1572 | ||
1573 | /* Note, __builtin_vec_insert_<xxx> has vector and scalar types | |
1574 | reversed. */ | |
1575 | *res = resolved; | |
1576 | return build_call_expr (call, 3, arg1, arg0, arg2); | |
1577 | } | |
1578 | ||
1579 | /* Build *(((arg1_inner_type*) & (vector type){arg1}) + arg2) = arg0 with | |
1580 | VIEW_CONVERT_EXPR. i.e.: | |
1581 | D.3192 = v1; | |
1582 | _1 = n & 3; | |
1583 | VIEW_CONVERT_EXPR<int[4]>(D.3192)[_1] = i; | |
1584 | v1 = D.3192; | |
1585 | D.3194 = v1; */ | |
1586 | if (TYPE_VECTOR_SUBPARTS (arg1_type) == 1) | |
1587 | arg2 = build_int_cst (TREE_TYPE (arg2), 0); | |
1588 | else | |
1589 | { | |
1590 | tree c = build_int_cst (TREE_TYPE (arg2), | |
1591 | TYPE_VECTOR_SUBPARTS (arg1_type) - 1); | |
1592 | arg2 = build_binary_op (loc, BIT_AND_EXPR, arg2, c, 0); | |
1593 | } | |
1594 | ||
1595 | tree decl = build_decl (loc, VAR_DECL, NULL_TREE, arg1_type); | |
1596 | DECL_EXTERNAL (decl) = 0; | |
1597 | TREE_PUBLIC (decl) = 0; | |
1598 | DECL_CONTEXT (decl) = current_function_decl; | |
1599 | TREE_USED (decl) = 1; | |
1600 | TREE_TYPE (decl) = arg1_type; | |
1601 | TREE_READONLY (decl) = TYPE_READONLY (arg1_type); | |
1602 | TREE_ADDRESSABLE (decl) = 1; | |
1603 | ||
1604 | tree stmt; | |
1605 | if (c_dialect_cxx ()) | |
1606 | { | |
1607 | stmt = build4 (TARGET_EXPR, arg1_type, decl, arg1, NULL_TREE, NULL_TREE); | |
1608 | SET_EXPR_LOCATION (stmt, loc); | |
1609 | } | |
1610 | else | |
1611 | { | |
1612 | DECL_INITIAL (decl) = arg1; | |
1613 | stmt = build1 (DECL_EXPR, arg1_type, decl); | |
1614 | SET_EXPR_LOCATION (stmt, loc); | |
1615 | stmt = build1 (COMPOUND_LITERAL_EXPR, arg1_type, stmt); | |
1616 | } | |
93b5a667 | 1617 | |
ab3f5b71 BS |
1618 | if (TARGET_VSX) |
1619 | { | |
1620 | stmt = build_array_ref (loc, stmt, arg2); | |
1621 | stmt = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg0), stmt, | |
1622 | convert (TREE_TYPE (stmt), arg0)); | |
1623 | stmt = build2 (COMPOUND_EXPR, arg1_type, stmt, decl); | |
1624 | } | |
1625 | else | |
1626 | { | |
1627 | tree arg1_inner_type = TREE_TYPE (arg1_type); | |
1628 | tree innerptrtype = build_pointer_type (arg1_inner_type); | |
93b5a667 BS |
1629 | stmt = build_unary_op (loc, ADDR_EXPR, stmt, 0); |
1630 | stmt = convert (innerptrtype, stmt); | |
1631 | stmt = build_binary_op (loc, PLUS_EXPR, stmt, arg2, 1); | |
1632 | stmt = build_indirect_ref (loc, stmt, RO_NULL); | |
ab3f5b71 BS |
1633 | stmt = build2 (MODIFY_EXPR, TREE_TYPE (stmt), stmt, |
1634 | convert (TREE_TYPE (stmt), arg0)); | |
1635 | stmt = build2 (COMPOUND_EXPR, arg1_type, stmt, decl); | |
1636 | } | |
93b5a667 | 1637 | |
ab3f5b71 BS |
1638 | *res = resolved; |
1639 | return stmt; | |
1640 | } | |
93b5a667 | 1641 | |
ab3f5b71 BS |
1642 | /* Resolve an overloaded vec_step call and return a tree expression for |
1643 | the resolved call if successful. NARGS is the number of arguments to | |
1644 | the call. ARGLIST contains the arguments. RES must be set to indicate | |
1645 | the status of the resolution attempt. */ | |
93b5a667 | 1646 | |
ab3f5b71 BS |
1647 | static tree |
1648 | resolve_vec_step (resolution *res, vec<tree, va_gc> *arglist, unsigned nargs) | |
1649 | { | |
1650 | if (nargs != 1) | |
93b5a667 | 1651 | { |
ab3f5b71 BS |
1652 | error ("builtin %qs only accepts 1 argument", "vec_step"); |
1653 | *res = resolved; | |
1654 | return error_mark_node; | |
1655 | } | |
93b5a667 | 1656 | |
ab3f5b71 BS |
1657 | tree arg0 = (*arglist)[0]; |
1658 | tree arg0_type = TREE_TYPE (arg0); | |
93b5a667 | 1659 | |
ab3f5b71 BS |
1660 | if (TREE_CODE (arg0_type) != VECTOR_TYPE) |
1661 | { | |
1662 | *res = resolved_bad; | |
1663 | return error_mark_node; | |
1664 | } | |
93b5a667 | 1665 | |
ab3f5b71 BS |
1666 | *res = resolved; |
1667 | return build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (arg0_type)); | |
1668 | } | |
93b5a667 | 1669 | |
ab3f5b71 BS |
1670 | /* Look for a matching instance in a chain of instances. INSTANCE points to |
1671 | the chain of instances; INSTANCE_CODE is the code identifying the specific | |
1672 | built-in being searched for; FCODE is the overloaded function code; TYPES | |
3fce8097 CL |
1673 | contains an array of NARGS types that must match the types of the |
1674 | instance's parameters; ARGS contains an array of NARGS arguments to be | |
1675 | passed to the instance; and NARGS is the number of built-in arguments to | |
1676 | check. If found, resolve the built-in and return it, unless the built-in | |
1677 | is not supported in context. In that case, set UNSUPPORTED_BUILTIN to | |
1678 | true. If we don't match, return error_mark_node and leave | |
1679 | UNSUPPORTED_BUILTIN alone. */ | |
93b5a667 | 1680 | |
ab3f5b71 BS |
1681 | tree |
1682 | find_instance (bool *unsupported_builtin, ovlddata **instance, | |
1683 | rs6000_gen_builtins instance_code, | |
1684 | rs6000_gen_builtins fcode, | |
3fce8097 | 1685 | tree *types, tree *args, int nargs) |
ab3f5b71 BS |
1686 | { |
1687 | while (*instance && (*instance)->bifid != instance_code) | |
1688 | *instance = (*instance)->next; | |
93b5a667 | 1689 | |
ab3f5b71 BS |
1690 | ovlddata *inst = *instance; |
1691 | gcc_assert (inst != NULL); | |
497bde3a KL |
1692 | /* It is possible for an instance to require a data type that isn't |
1693 | defined on this target, in which case inst->fntype will be NULL. */ | |
1694 | if (!inst->fntype) | |
1695 | return error_mark_node; | |
ab3f5b71 | 1696 | tree fntype = rs6000_builtin_info[inst->bifid].fntype; |
3fce8097 CL |
1697 | tree argtype = TYPE_ARG_TYPES (fntype); |
1698 | bool args_compatible = true; | |
93b5a667 | 1699 | |
3fce8097 CL |
1700 | for (int i = 0; i < nargs; i++) |
1701 | { | |
1702 | tree parmtype = TREE_VALUE (argtype); | |
1703 | if (!rs6000_builtin_type_compatible (types[i], parmtype)) | |
1704 | { | |
1705 | args_compatible = false; | |
1706 | break; | |
1707 | } | |
1708 | argtype = TREE_CHAIN (argtype); | |
1709 | } | |
1710 | ||
1711 | if (args_compatible) | |
ab3f5b71 BS |
1712 | { |
1713 | if (rs6000_builtin_decl (inst->bifid, false) != error_mark_node | |
1714 | && rs6000_builtin_is_supported (inst->bifid)) | |
93b5a667 | 1715 | { |
ab3f5b71 | 1716 | tree ret_type = TREE_TYPE (inst->fntype); |
3fce8097 | 1717 | return altivec_build_resolved_builtin (args, nargs, fntype, ret_type, |
ab3f5b71 | 1718 | inst->bifid, fcode); |
93b5a667 BS |
1719 | } |
1720 | else | |
ab3f5b71 BS |
1721 | *unsupported_builtin = true; |
1722 | } | |
1723 | ||
1724 | return error_mark_node; | |
1725 | } | |
1726 | ||
1727 | /* Implementation of the resolve_overloaded_builtin target hook, to | |
1728 | support Altivec's overloaded builtins. */ | |
1729 | ||
1730 | tree | |
1731 | altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, | |
1732 | void *passed_arglist) | |
1733 | { | |
1734 | rs6000_gen_builtins fcode | |
1735 | = (rs6000_gen_builtins) DECL_MD_FUNCTION_CODE (fndecl); | |
1736 | ||
1737 | /* Return immediately if this isn't an overload. */ | |
1738 | if (fcode <= RS6000_OVLD_NONE) | |
1739 | return NULL_TREE; | |
1740 | ||
1741 | if (TARGET_DEBUG_BUILTIN) | |
1742 | fprintf (stderr, "altivec_resolve_overloaded_builtin, code = %4d, %s\n", | |
1743 | (int) fcode, IDENTIFIER_POINTER (DECL_NAME (fndecl))); | |
1744 | ||
1745 | /* vec_lvsl and vec_lvsr are deprecated for use with LE element order. */ | |
1746 | if (fcode == RS6000_OVLD_VEC_LVSL && !BYTES_BIG_ENDIAN) | |
1747 | warning (OPT_Wdeprecated, | |
1748 | "%<vec_lvsl%> is deprecated for little endian; use " | |
1749 | "assignment for unaligned loads and stores"); | |
1750 | else if (fcode == RS6000_OVLD_VEC_LVSR && !BYTES_BIG_ENDIAN) | |
1751 | warning (OPT_Wdeprecated, | |
1752 | "%<vec_lvsr%> is deprecated for little endian; use " | |
1753 | "assignment for unaligned loads and stores"); | |
1754 | ||
ab3f5b71 BS |
1755 | /* Gather the arguments and their types into arrays for easier handling. */ |
1756 | tree fnargs = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); | |
1757 | tree types[MAX_OVLD_ARGS]; | |
1758 | tree args[MAX_OVLD_ARGS]; | |
93b5a667 | 1759 | unsigned int n; |
ab3f5b71 | 1760 | |
b28b92bc BS |
1761 | /* Count the number of expected arguments. */ |
1762 | unsigned expected_args = 0; | |
1763 | for (tree chain = fnargs; | |
1764 | chain && !VOID_TYPE_P (TREE_VALUE (chain)); | |
1765 | chain = TREE_CHAIN (chain)) | |
1766 | expected_args++; | |
1767 | ||
1768 | vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist); | |
1769 | unsigned int nargs = vec_safe_length (arglist); | |
1770 | ||
38db4834 KL |
1771 | /* If the number of arguments did not match the prototype, return NULL |
1772 | and the generic code will issue the appropriate error message. Skip | |
1773 | this test for functions where we don't fully describe all the possible | |
1774 | overload signatures in rs6000-overload.def (because they aren't relevant | |
1775 | to the expansion here). If we don't, we get confusing error messages. */ | |
1776 | /* As an example, for vec_splats we have: | |
1777 | ||
1778 | ; There are no actual builtins for vec_splats. There is special handling for | |
1779 | ; this in altivec_resolve_overloaded_builtin in rs6000-c.cc, where the call | |
1780 | ; is replaced by a constructor. The single overload here causes | |
1781 | ; __builtin_vec_splats to be registered with the front end so that can happen. | |
1782 | [VEC_SPLATS, vec_splats, __builtin_vec_splats] | |
1783 | vsi __builtin_vec_splats (vsi); | |
1784 | ABS_V4SI SPLATS_FAKERY | |
1785 | ||
1786 | So even though __builtin_vec_splats accepts all vector types, the | |
1787 | infrastructure cheats and just records one prototype. We end up getting | |
1788 | an error message that refers to this specific prototype even when we | |
1789 | are handling a different argument type. That is completely confusing | |
1790 | to the user, so it's best to let these cases be handled individually | |
1791 | in the resolve_vec_splats, etc., helper functions. */ | |
1792 | ||
1793 | if (expected_args != nargs | |
1794 | && !(fcode == RS6000_OVLD_VEC_PROMOTE | |
1795 | || fcode == RS6000_OVLD_VEC_SPLATS | |
1796 | || fcode == RS6000_OVLD_VEC_EXTRACT | |
1797 | || fcode == RS6000_OVLD_VEC_INSERT | |
1798 | || fcode == RS6000_OVLD_VEC_STEP)) | |
1799 | return NULL; | |
1800 | ||
93b5a667 BS |
1801 | for (n = 0; |
1802 | !VOID_TYPE_P (TREE_VALUE (fnargs)) && n < nargs; | |
1803 | fnargs = TREE_CHAIN (fnargs), n++) | |
1804 | { | |
1805 | tree decl_type = TREE_VALUE (fnargs); | |
1806 | tree arg = (*arglist)[n]; | |
93b5a667 BS |
1807 | |
1808 | if (arg == error_mark_node) | |
1809 | return error_mark_node; | |
1810 | ||
1811 | if (n >= MAX_OVLD_ARGS) | |
1812 | abort (); | |
1813 | ||
1814 | arg = default_conversion (arg); | |
ab3f5b71 | 1815 | tree type = TREE_TYPE (arg); |
93b5a667 BS |
1816 | |
1817 | /* The C++ front-end converts float * to const void * using | |
1818 | NOP_EXPR<const void *> (NOP_EXPR<void *> (x)). */ | |
93b5a667 BS |
1819 | if (POINTER_TYPE_P (type) |
1820 | && TREE_CODE (arg) == NOP_EXPR | |
1821 | && lang_hooks.types_compatible_p (TREE_TYPE (arg), | |
1822 | const_ptr_type_node) | |
1823 | && lang_hooks.types_compatible_p (TREE_TYPE (TREE_OPERAND (arg, 0)), | |
1824 | ptr_type_node)) | |
1825 | { | |
1826 | arg = TREE_OPERAND (arg, 0); | |
1827 | type = TREE_TYPE (arg); | |
1828 | } | |
1829 | ||
1830 | /* Remove the const from the pointers to simplify the overload | |
1831 | matching further down. */ | |
1832 | if (POINTER_TYPE_P (decl_type) | |
1833 | && POINTER_TYPE_P (type) | |
1834 | && TYPE_QUALS (TREE_TYPE (type)) != 0) | |
1835 | { | |
1836 | if (TYPE_READONLY (TREE_TYPE (type)) | |
1837 | && !TYPE_READONLY (TREE_TYPE (decl_type))) | |
018805e2 ML |
1838 | warning (0, "passing argument %d of %qE discards %qs " |
1839 | "qualifier from pointer target type", n + 1, fndecl, | |
1840 | "const"); | |
93b5a667 BS |
1841 | type = build_qualified_type (TREE_TYPE (type), 0); |
1842 | type = build_pointer_type (type); | |
1843 | arg = fold_convert (type, arg); | |
1844 | } | |
1845 | ||
1846 | /* For RS6000_OVLD_VEC_LXVL, convert any const * to its non constant | |
1847 | equivalent to simplify the overload matching below. */ | |
ab3f5b71 BS |
1848 | if (fcode == RS6000_OVLD_VEC_LXVL |
1849 | && POINTER_TYPE_P (type) | |
1850 | && TYPE_READONLY (TREE_TYPE (type))) | |
93b5a667 | 1851 | { |
ab3f5b71 BS |
1852 | type = build_qualified_type (TREE_TYPE (type), 0); |
1853 | type = build_pointer_type (type); | |
1854 | arg = fold_convert (type, arg); | |
93b5a667 BS |
1855 | } |
1856 | ||
1857 | args[n] = arg; | |
1858 | types[n] = type; | |
1859 | } | |
1860 | ||
b28b92bc BS |
1861 | /* Some overloads require special handling. */ |
1862 | tree returned_expr = NULL; | |
1863 | resolution res = unresolved; | |
1864 | ||
1865 | if (fcode == RS6000_OVLD_VEC_MUL) | |
1866 | returned_expr = resolve_vec_mul (&res, args, types, loc); | |
1867 | else if (fcode == RS6000_OVLD_VEC_CMPNE) | |
1868 | returned_expr = resolve_vec_cmpne (&res, args, types, loc); | |
1869 | else if (fcode == RS6000_OVLD_VEC_ADDE || fcode == RS6000_OVLD_VEC_SUBE) | |
1870 | returned_expr = resolve_vec_adde_sube (&res, fcode, args, types, loc); | |
1871 | else if (fcode == RS6000_OVLD_VEC_ADDEC || fcode == RS6000_OVLD_VEC_SUBEC) | |
1872 | returned_expr = resolve_vec_addec_subec (&res, fcode, args, types, loc); | |
1873 | else if (fcode == RS6000_OVLD_VEC_SPLATS || fcode == RS6000_OVLD_VEC_PROMOTE) | |
1874 | returned_expr = resolve_vec_splats (&res, fcode, arglist, nargs); | |
1875 | else if (fcode == RS6000_OVLD_VEC_EXTRACT) | |
1876 | returned_expr = resolve_vec_extract (&res, arglist, nargs, loc); | |
1877 | else if (fcode == RS6000_OVLD_VEC_INSERT) | |
1878 | returned_expr = resolve_vec_insert (&res, arglist, nargs, loc); | |
1879 | else if (fcode == RS6000_OVLD_VEC_STEP) | |
1880 | returned_expr = resolve_vec_step (&res, arglist, nargs); | |
1881 | ||
1882 | if (res == resolved) | |
1883 | return returned_expr; | |
1884 | ||
1885 | /* "Regular" built-in functions and overloaded functions share a namespace | |
1886 | for some arrays, like rs6000_builtin_decls. But rs6000_overload_info | |
1887 | only has information for the overloaded functions, so we need an | |
1888 | adjusted index for that. */ | |
1889 | unsigned int adj_fcode = fcode - RS6000_OVLD_NONE; | |
1890 | ||
1891 | if (res == resolved_bad) | |
1892 | { | |
1893 | const char *name = rs6000_overload_info[adj_fcode].ovld_name; | |
1894 | error ("invalid parameter combination for AltiVec intrinsic %qs", name); | |
1895 | return error_mark_node; | |
1896 | } | |
1897 | ||
ab3f5b71 BS |
1898 | bool unsupported_builtin = false; |
1899 | rs6000_gen_builtins instance_code; | |
1900 | bool supported = false; | |
1901 | ovlddata *instance = rs6000_overload_info[adj_fcode].first_instance; | |
1902 | gcc_assert (instance != NULL); | |
93b5a667 | 1903 | |
ab3f5b71 BS |
1904 | /* Functions with no arguments can have only one overloaded instance. */ |
1905 | gcc_assert (nargs > 0 || !instance->next); | |
93b5a667 | 1906 | |
ab3f5b71 BS |
1907 | /* Standard overload processing involves determining whether an instance |
1908 | exists that is type-compatible with the overloaded function call. In | |
1909 | a couple of cases, we need to do some extra processing to disambiguate | |
1910 | between multiple compatible instances. */ | |
1911 | switch (fcode) | |
1912 | { | |
1913 | /* Need to special case __builtin_cmpb because the overloaded forms | |
1914 | of this function take (unsigned int, unsigned int) or (unsigned | |
1915 | long long int, unsigned long long int). Since C conventions | |
1916 | allow the respective argument types to be implicitly coerced into | |
1917 | each other, the default handling does not provide adequate | |
1918 | discrimination between the desired forms of the function. */ | |
1919 | case RS6000_OVLD_SCAL_CMPB: | |
93b5a667 BS |
1920 | { |
1921 | machine_mode arg1_mode = TYPE_MODE (types[0]); | |
1922 | machine_mode arg2_mode = TYPE_MODE (types[1]); | |
1923 | ||
93b5a667 BS |
1924 | /* If any supplied arguments are wider than 32 bits, resolve to |
1925 | 64-bit variant of built-in function. */ | |
1926 | if (GET_MODE_PRECISION (arg1_mode) > 32 | |
1927 | || GET_MODE_PRECISION (arg2_mode) > 32) | |
1928 | /* Assure all argument and result types are compatible with | |
1929 | the built-in function represented by RS6000_BIF_CMPB. */ | |
ab3f5b71 | 1930 | instance_code = RS6000_BIF_CMPB; |
93b5a667 BS |
1931 | else |
1932 | /* Assure all argument and result types are compatible with | |
1933 | the built-in function represented by RS6000_BIF_CMPB_32. */ | |
ab3f5b71 | 1934 | instance_code = RS6000_BIF_CMPB_32; |
93b5a667 | 1935 | |
ab3f5b71 | 1936 | tree call = find_instance (&unsupported_builtin, &instance, |
3fce8097 | 1937 | instance_code, fcode, types, args, nargs); |
ab3f5b71 BS |
1938 | if (call != error_mark_node) |
1939 | return call; | |
1940 | break; | |
93b5a667 | 1941 | } |
ab3f5b71 | 1942 | case RS6000_OVLD_VEC_VSIE: |
93b5a667 BS |
1943 | { |
1944 | machine_mode arg1_mode = TYPE_MODE (types[0]); | |
1945 | ||
93b5a667 BS |
1946 | /* If supplied first argument is wider than 64 bits, resolve to |
1947 | 128-bit variant of built-in function. */ | |
1948 | if (GET_MODE_PRECISION (arg1_mode) > 64) | |
1949 | { | |
86df278d CL |
1950 | /* If first argument is of float variety, choose the variant that |
1951 | expects __ieee128 argument. If the first argument is vector | |
1952 | int, choose the variant that expects vector unsigned | |
1953 | __int128 argument. Otherwise, expect scalar __int128 argument. | |
1954 | */ | |
93b5a667 | 1955 | if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT) |
ab3f5b71 | 1956 | instance_code = RS6000_BIF_VSIEQPF; |
86df278d CL |
1957 | else if (GET_MODE_CLASS (arg1_mode) == MODE_VECTOR_INT) |
1958 | instance_code = RS6000_BIF_VSIEQPV; | |
93b5a667 | 1959 | else |
ab3f5b71 | 1960 | instance_code = RS6000_BIF_VSIEQP; |
93b5a667 BS |
1961 | } |
1962 | else | |
1963 | { | |
1964 | /* If first argument is of float variety, choose variant | |
1965 | that expects double argument. Otherwise, expect | |
1966 | long long int argument. */ | |
1967 | if (GET_MODE_CLASS (arg1_mode) == MODE_FLOAT) | |
ab3f5b71 | 1968 | instance_code = RS6000_BIF_VSIEDPF; |
93b5a667 | 1969 | else |
ab3f5b71 | 1970 | instance_code = RS6000_BIF_VSIEDP; |
93b5a667 BS |
1971 | } |
1972 | ||
b51795c8 CL |
1973 | tree call = find_instance (&unsupported_builtin, &instance, |
1974 | instance_code, fcode, types, args, nargs); | |
1975 | if (call != error_mark_node) | |
1976 | return call; | |
1977 | break; | |
1978 | } | |
1979 | case RS6000_OVLD_VEC_REPLACE_UN: | |
1980 | { | |
1981 | machine_mode arg2_mode = TYPE_MODE (types[1]); | |
1982 | ||
1983 | if (arg2_mode == SImode) | |
1984 | /* Signed and unsigned are handled the same. */ | |
1985 | instance_code = RS6000_BIF_VREPLACE_UN_USI; | |
1986 | else if (arg2_mode == SFmode) | |
1987 | instance_code = RS6000_BIF_VREPLACE_UN_SF; | |
1988 | else if (arg2_mode == DImode) | |
1989 | /* Signed and unsigned are handled the same. */ | |
1990 | instance_code = RS6000_BIF_VREPLACE_UN_UDI; | |
1991 | else if (arg2_mode == DFmode) | |
1992 | instance_code = RS6000_BIF_VREPLACE_UN_DF; | |
1993 | else | |
1994 | break; | |
1995 | ||
ab3f5b71 | 1996 | tree call = find_instance (&unsupported_builtin, &instance, |
3fce8097 | 1997 | instance_code, fcode, types, args, nargs); |
ab3f5b71 BS |
1998 | if (call != error_mark_node) |
1999 | return call; | |
2000 | break; | |
2001 | } | |
2002 | default: | |
2003 | /* Standard overload processing. Look for an instance with compatible | |
2004 | parameter types. If it is supported in the current context, resolve | |
2005 | the overloaded call to that instance. */ | |
2006 | for (; instance != NULL; instance = instance->next) | |
2007 | { | |
4ec62dba BS |
2008 | /* It is possible for an instance to require a data type that isn't |
2009 | defined on this target, in which case instance->fntype will be | |
2010 | NULL. */ | |
2011 | if (!instance->fntype) | |
2012 | continue; | |
2013 | ||
ab3f5b71 BS |
2014 | bool mismatch = false; |
2015 | tree nextparm = TYPE_ARG_TYPES (instance->fntype); | |
93b5a667 | 2016 | |
ab3f5b71 BS |
2017 | for (unsigned int arg_i = 0; |
2018 | arg_i < nargs && nextparm != NULL; | |
2019 | arg_i++) | |
2020 | { | |
2021 | tree parmtype = TREE_VALUE (nextparm); | |
2022 | if (!rs6000_builtin_type_compatible (types[arg_i], parmtype)) | |
2023 | { | |
2024 | mismatch = true; | |
2025 | break; | |
2026 | } | |
2027 | nextparm = TREE_CHAIN (nextparm); | |
2028 | } | |
93b5a667 | 2029 | |
ab3f5b71 BS |
2030 | if (mismatch) |
2031 | continue; | |
2032 | ||
2033 | supported = rs6000_builtin_is_supported (instance->bifid); | |
2034 | if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node | |
2035 | && supported) | |
2036 | { | |
2037 | tree fntype = rs6000_builtin_info[instance->bifid].fntype; | |
2038 | tree ret_type = TREE_TYPE (instance->fntype); | |
2039 | return altivec_build_resolved_builtin (args, nargs, fntype, | |
2040 | ret_type, instance->bifid, | |
2041 | fcode); | |
2042 | } | |
2043 | else | |
2044 | { | |
93b5a667 | 2045 | unsupported_builtin = true; |
ab3f5b71 BS |
2046 | break; |
2047 | } | |
2048 | } | |
2049 | } | |
93b5a667 | 2050 | |
ab3f5b71 BS |
2051 | if (unsupported_builtin) |
2052 | { | |
2053 | const char *name = rs6000_overload_info[adj_fcode].ovld_name; | |
2054 | if (!supported) | |
2055 | { | |
2056 | /* Indicate that the instantiation of the overloaded builtin | |
2057 | name is not available with the target flags in effect. */ | |
2058 | rs6000_gen_builtins fcode = (rs6000_gen_builtins) instance->bifid; | |
2059 | rs6000_invalid_builtin (fcode); | |
2060 | /* Provide clarity of the relationship between the overload | |
2061 | and the instantiation. */ | |
2062 | const char *internal_name | |
2063 | = rs6000_builtin_info[instance->bifid].bifname; | |
2064 | rich_location richloc (line_table, input_location); | |
2065 | inform (&richloc, | |
2066 | "overloaded builtin %qs is implemented by builtin %qs", | |
2067 | name, internal_name); | |
2068 | } | |
2069 | else | |
2070 | error ("%qs is not supported in this compiler configuration", name); | |
93b5a667 | 2071 | |
ab3f5b71 BS |
2072 | return error_mark_node; |
2073 | } | |
93b5a667 | 2074 | |
ab3f5b71 BS |
2075 | /* If we fall through to here, there were no compatible instances. */ |
2076 | const char *name = rs6000_overload_info[adj_fcode].ovld_name; | |
2077 | error ("invalid parameter combination for AltiVec intrinsic %qs", name); | |
2078 | return error_mark_node; | |
93b5a667 | 2079 | } |