go: update builtin function attributes
[official-gcc.git] / gcc / config / s390 / s390-c.cc
blob311d74a275e21ea0fd787c3aea5dff0245c9dcd8
1 /* Language specific subroutines used for code generation on IBM S/390
2 and zSeries
3 Copyright (C) 2015-2025 Free Software Foundation, Inc.
5 Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
7 This file is part of GCC.
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 by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>.
23 Based on gcc/config/rs6000/rs6000-c.cc.
25 In GCC terms this file belongs to the frontend. It will be
26 compiled with -DIN_GCC_FRONTEND. With that rtl.h cannot be
27 included anymore - a mechanism supposed to avoid adding frontend -
28 backend dependencies. */
30 #define IN_TARGET_CODE 1
32 #include "config.h"
33 #include "system.h"
34 #include "coretypes.h"
35 #include "target.h"
36 #include "tree.h"
37 #include "c-family/c-common.h"
38 #include "c/c-tree.h"
39 #include "memmodel.h"
40 #include "tm_p.h"
41 #include "stringpool.h"
42 #include "c-family/c-pragma.h"
43 #include "langhooks.h"
44 #include "tree-pretty-print.h"
46 #include "s390-builtins.h"
48 static GTY(()) tree __vector_keyword;
49 static GTY(()) tree vector_keyword;
50 static GTY(()) tree __bool_keyword;
51 static GTY(()) tree bool_keyword;
52 static GTY(()) tree _Bool_keyword;
55 /* Generate an array holding all the descriptions of variants of
56 overloaded builtins defined with OB_DEF_VAR in
57 s390-builtins.def. */
58 static enum s390_builtin_ov_type_index
59 type_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX + 1] =
61 #undef B_DEF
62 #undef OB_DEF
63 #undef OB_DEF_VAR
64 #define B_DEF(...)
65 #define OB_DEF(...)
66 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, OPFLAGS, FNTYPE) FNTYPE,
67 #include "s390-builtins.def"
68 BT_OV_MAX
72 /* Generate an array indexed by an overloaded builtin index returning
73 the first index in desc_for_overloaded_builtin_var where the
74 variants for the builtin can be found. */
75 static enum s390_overloaded_builtin_vars
76 desc_start_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
78 #undef B_DEF
79 #undef OB_DEF
80 #undef OB_DEF_VAR
81 #define B_DEF(...)
82 #define OB_DEF(NAME, FIRST_VAR_NAME,...) \
83 S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
84 #define OB_DEF_VAR(...)
85 #include "s390-builtins.def"
86 S390_OVERLOADED_BUILTIN_VAR_MAX
89 /* Generate an array indexed by an overloaded builtin index returning
90 the last index in desc_for_overloaded_builtin_var where the
91 variants for the builtin can be found. */
92 static enum s390_overloaded_builtin_vars
93 desc_end_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
95 #undef B_DEF
96 #undef OB_DEF
97 #undef OB_DEF_VAR
98 #define B_DEF(...)
99 #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...) \
100 S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
101 #define OB_DEF_VAR(...)
102 #include "s390-builtins.def"
103 S390_OVERLOADED_BUILTIN_VAR_MAX
106 static enum s390_builtin_type_index
107 s390_builtin_ov_types[BT_OV_MAX][MAX_OV_OPERANDS] =
109 #undef DEF_TYPE
110 #undef DEF_POINTER_TYPE
111 #undef DEF_DISTINCT_TYPE
112 #undef DEF_VECTOR_TYPE
113 #undef DEF_OPAQUE_VECTOR_TYPE
114 #undef DEF_FN_TYPE
115 #undef DEF_OV_TYPE
116 #define DEF_TYPE(...)
117 #define DEF_POINTER_TYPE(...)
118 #define DEF_DISTINCT_TYPE(...)
119 #define DEF_VECTOR_TYPE(...)
120 #define DEF_OPAQUE_VECTOR_TYPE(...)
121 #define DEF_FN_TYPE(...)
122 #define DEF_OV_TYPE(INDEX, args...) { args },
123 #include "s390-builtin-types.def"
126 static const enum s390_builtins
127 bt_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX] = {
128 #undef B_DEF
129 #undef OB_DEF
130 #undef OB_DEF_VAR
131 #define B_DEF(...)
132 #define OB_DEF(...)
133 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
135 #include "s390-builtins.def"
138 /* In addition to calling fold_convert for EXPR of type TYPE, also
139 call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
140 hiding there (PR47197). */
141 tree
142 fully_fold_convert (tree type, tree expr)
144 tree result = fold_convert (type, expr);
145 bool maybe_const = true;
147 if (!c_dialect_cxx ())
148 result = c_fully_fold (result, false, &maybe_const);
150 return result;
153 /* Unify the different variants to the same nodes in order to keep the
154 code working with it simple. */
155 static cpp_hashnode *
156 s390_categorize_keyword (const cpp_token *tok)
158 if (tok->type == CPP_NAME)
160 cpp_hashnode *ident = tok->val.node.node;
162 if (ident == C_CPP_HASHNODE (vector_keyword))
163 return C_CPP_HASHNODE (__vector_keyword);
165 if (ident == C_CPP_HASHNODE (bool_keyword))
166 return C_CPP_HASHNODE (__bool_keyword);
168 if (ident == C_CPP_HASHNODE (_Bool_keyword))
169 return C_CPP_HASHNODE (__bool_keyword);
170 return ident;
173 return 0;
177 /* Helper function to find out which RID_INT_N_* code is the one for
178 __int128, if any. Returns RID_MAX+1 if none apply, which is safe
179 (for our purposes, since we always expect to have __int128) to
180 compare against. */
181 static inline int
182 rid_int128 (void)
184 for (int i = 0; i < NUM_INT_N_ENTS; ++i)
185 if (int_n_enabled_p[i]
186 && int_n_data[i].bitsize == 128)
187 return RID_INT_N_0 + i;
189 return RID_MAX + 1;
193 /* Called to decide whether a conditional macro should be expanded.
194 Since we have exactly one such macro (i.e, 'vector'), we do not
195 need to examine the 'tok' parameter. */
197 static cpp_hashnode *
198 s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
200 cpp_hashnode *expand_this = tok->val.node.node;
201 cpp_hashnode *ident;
202 static bool expand_bool_p = false;
203 int idx = 0;
204 enum rid rid_code;
206 /* The vector keyword is only expanded if the machine actually
207 provides hardware support. */
208 if (!TARGET_ZVECTOR)
209 return NULL;
211 ident = s390_categorize_keyword (tok);
213 /* Triggered when we picked a different variant in
214 s390_categorize_keyword. */
215 if (ident != expand_this)
216 expand_this = NULL;
218 /* The vector keyword has been found already and we remembered to
219 expand the next bool. */
220 if (expand_bool_p && ident == C_CPP_HASHNODE (__bool_keyword))
222 expand_bool_p = false;
223 return ident;
226 if (ident != C_CPP_HASHNODE (__vector_keyword))
227 return expand_this;
230 tok = cpp_peek_token (pfile, idx++);
231 while (tok->type == CPP_PADDING);
232 ident = s390_categorize_keyword (tok);
234 if (!ident)
235 return expand_this;
237 /* vector bool - remember to expand the next bool. */
238 if (ident == C_CPP_HASHNODE (__bool_keyword))
240 expand_bool_p = true;
241 return C_CPP_HASHNODE (__vector_keyword);
244 /* The boost libraries have code with Iterator::vector vector in it.
245 If we allow the normal handling, this module will be called
246 recursively, and the vector will be skipped.; */
247 if (ident == C_CPP_HASHNODE (__vector_keyword))
248 return expand_this;
250 rid_code = (enum rid)(ident->rid_code);
252 if (cpp_macro_p (ident))
254 /* Now actually fetch the tokens we "peeked" before and do a
255 lookahead for the next. */
257 (void) cpp_get_token (pfile);
258 while (--idx > 0);
260 tok = cpp_peek_token (pfile, idx++);
261 while (tok->type == CPP_PADDING);
262 ident = s390_categorize_keyword (tok);
264 if (ident == C_CPP_HASHNODE (__bool_keyword))
266 expand_bool_p = true;
267 return C_CPP_HASHNODE (__vector_keyword);
269 else if (ident)
270 rid_code = (enum rid)(ident->rid_code);
273 /* vector keyword followed by type identifier: vector unsigned,
274 vector long, ...
275 Types consisting of more than one identifier are not supported by
276 zvector e.g. long long, long double, unsigned long int. */
277 if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
278 || rid_code == RID_SHORT || rid_code == RID_SIGNED
279 || rid_code == RID_INT || rid_code == RID_CHAR
280 || (rid_code == RID_FLOAT && TARGET_VXE)
281 || rid_code == RID_DOUBLE
282 || rid_code == rid_int128 ())
284 expand_this = C_CPP_HASHNODE (__vector_keyword);
285 /* If the next keyword is bool, it will need to be expanded as
286 well. */
288 tok = cpp_peek_token (pfile, idx++);
289 while (tok->type == CPP_PADDING);
290 ident = s390_categorize_keyword (tok);
292 /* __vector long __bool a; */
293 if (ident == C_CPP_HASHNODE (__bool_keyword))
294 expand_bool_p = true;
296 /* If there are more tokens to check. */
297 else if (ident)
299 /* Triggered with: __vector long long __bool a; */
301 tok = cpp_peek_token (pfile, idx++);
302 while (tok->type == CPP_PADDING);
303 ident = s390_categorize_keyword (tok);
305 if (ident == C_CPP_HASHNODE (__bool_keyword))
306 expand_bool_p = true;
310 return expand_this;
313 /* Helper function that defines or undefines macros. If SET is true, the macro
314 MACRO_DEF is defined. If SET is false, the macro MACRO_UNDEF is undefined.
315 Nothing is done if SET and WAS_SET have the same value. */
316 template <typename F>
317 static void
318 s390_def_or_undef_macro (cpp_reader *pfile, F is_set,
319 const struct cl_target_option *old_opts,
320 const struct cl_target_option *new_opts,
321 const char *macro_def, const char *macro_undef)
323 bool was_set;
324 bool set;
326 was_set = (!old_opts) ? false : is_set (old_opts);
327 set = is_set (new_opts);
328 if (was_set == set)
329 return;
330 if (set)
331 cpp_define (pfile, macro_def);
332 else
333 cpp_undef (pfile, macro_undef);
336 struct target_flag_set_p
338 target_flag_set_p (unsigned int mask) : m_mask (mask) {}
340 bool
341 operator() (const struct cl_target_option *opts) const
343 return opts->x_target_flags & m_mask;
346 unsigned int m_mask;
349 /* Internal function to either define or undef the appropriate system
350 macros. */
351 static void
352 s390_cpu_cpp_builtins_internal (cpp_reader *pfile,
353 struct cl_target_option *opts,
354 const struct cl_target_option *old_opts)
356 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_OPT_HTM), old_opts,
357 opts, "__HTM__", "__HTM__");
358 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_OPT_VX), old_opts,
359 opts, "__VX__", "__VX__");
360 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR), old_opts,
361 opts, "__VEC__=10305", "__VEC__");
362 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR), old_opts,
363 opts, "__vector=__attribute__((vector_size(16)))",
364 "__vector__");
365 s390_def_or_undef_macro (
366 pfile, target_flag_set_p (MASK_ZVECTOR), old_opts, opts,
367 "__bool=__attribute__((s390_vector_bool)) unsigned", "__bool");
369 char macro_def[64];
370 gcc_assert (s390_arch != PROCESSOR_NATIVE);
371 sprintf (macro_def, "__ARCH__=%d", processor_table[s390_arch].arch_level);
372 cpp_undef (pfile, "__ARCH__");
373 cpp_define (pfile, macro_def);
375 s390_def_or_undef_macro (
376 pfile,
377 [] (const struct cl_target_option *opts) { return TARGET_VXE_P (opts); },
378 old_opts, opts, "__LONG_DOUBLE_VX__", "__LONG_DOUBLE_VX__");
380 if (!flag_iso)
382 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
383 old_opts, opts, "__VECTOR_KEYWORD_SUPPORTED__",
384 "__VECTOR_KEYWORD_SUPPORTED__");
385 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
386 old_opts, opts, "vector=vector", "vector");
387 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
388 old_opts, opts, "bool=bool", "bool");
389 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
390 old_opts, opts, "_Bool=_Bool", "_Bool");
391 if (TARGET_ZVECTOR_P (opts->x_target_flags) && __vector_keyword == NULL)
393 __vector_keyword = get_identifier ("__vector");
394 C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
396 vector_keyword = get_identifier ("vector");
397 C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
399 __bool_keyword = get_identifier ("__bool");
400 C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
402 bool_keyword = get_identifier ("bool");
403 C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
405 _Bool_keyword = get_identifier ("_Bool");
406 C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
408 /* Enable context-sensitive macros. */
409 cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
414 /* Define platform dependent macros. */
415 void
416 s390_cpu_cpp_builtins (cpp_reader *pfile)
418 struct cl_target_option opts;
420 cpp_assert (pfile, "cpu=s390");
421 cpp_assert (pfile, "machine=s390");
422 cpp_define (pfile, "__s390__");
423 if (TARGET_ZARCH)
424 cpp_define (pfile, "__zarch__");
425 if (TARGET_64BIT)
426 cpp_define (pfile, "__s390x__");
427 if (TARGET_LONG_DOUBLE_128)
428 cpp_define (pfile, "__LONG_DOUBLE_128__");
429 cl_target_option_save (&opts, &global_options, &global_options_set);
430 s390_cpu_cpp_builtins_internal (pfile, &opts, NULL);
431 cpp_define (pfile, "__GCC_ASM_FLAG_OUTPUTS__");
434 #if S390_USE_TARGET_ATTRIBUTE
435 /* Hook to validate the current #pragma GCC target and set the state, and
436 update the macros based on what was changed. If ARGS is NULL, then
437 POP_TARGET is used to reset the options. */
439 static bool
440 s390_pragma_target_parse (tree args, tree pop_target)
442 tree prev_tree = build_target_option_node (&global_options,
443 &global_options_set);
444 tree cur_tree;
446 if (! args)
447 cur_tree = pop_target;
448 else
450 cur_tree = s390_valid_target_attribute_tree (args, &global_options,
451 &global_options_set, true);
452 if (!cur_tree || cur_tree == error_mark_node)
454 cl_target_option_restore (&global_options, &global_options_set,
455 TREE_TARGET_OPTION (prev_tree));
456 return false;
460 target_option_current_node = cur_tree;
461 s390_activate_target_options (target_option_current_node);
464 struct cl_target_option *prev_opt;
465 struct cl_target_option *cur_opt;
467 /* Figure out the previous/current differences. */
468 prev_opt = TREE_TARGET_OPTION (prev_tree);
469 cur_opt = TREE_TARGET_OPTION (cur_tree);
471 /* For the definitions, ensure all newly defined macros are considered
472 as used for -Wunused-macros. There is no point warning about the
473 compiler predefined macros. */
474 cpp_options *cpp_opts = cpp_get_options (parse_in);
475 unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
477 cpp_opts->warn_unused_macros = 0;
479 /* Define all of the macros for new options that were just turned on. */
480 cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
481 s390_cpu_cpp_builtins_internal (parse_in, cur_opt, prev_opt);
482 cpp_stop_forcing_token_locations (parse_in);
484 cpp_opts->warn_unused_macros = saved_warn_unused_macros;
487 return true;
489 #endif
491 /* Expand builtins which can directly be mapped to tree expressions.
492 LOC - location information
493 FCODE - function code of the builtin
494 ARGLIST - value supposed to be passed as arguments
495 RETURN-TYPE - expected return type of the builtin */
496 static tree
497 s390_expand_overloaded_builtin (location_t loc,
498 unsigned fcode,
499 vec<tree, va_gc> *arglist,
500 tree return_type)
502 switch (fcode)
504 case S390_OVERLOADED_BUILTIN_s390_vec_step:
505 if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
507 error_at (loc, "builtin %qs can only be used on vector types",
508 "vec_step");
509 return error_mark_node;
511 return build_int_cst (NULL_TREE,
512 TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
513 case S390_OVERLOADED_BUILTIN_s390_vec_xl:
514 case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
515 case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
517 /* Build a vector type with the alignment of the source
518 location in order to enable correct alignment hints to be
519 generated for vl. */
520 unsigned align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[1])));
521 tree mem_type = build_aligned_type (return_type, align);
522 return build2 (MEM_REF, mem_type,
523 fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
524 build_int_cst (ptr_type_node, 0));
526 case S390_OVERLOADED_BUILTIN_s390_vec_xst:
527 case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
528 case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
530 /* Build a vector type with the alignment of the target
531 location in order to enable correct alignment hints to be
532 generated for vst. */
533 unsigned align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[2])));
534 tree mem_type = build_aligned_type (TREE_TYPE ((*arglist)[0]), align);
535 return build2 (MODIFY_EXPR, mem_type,
536 build2 (MEM_REF, mem_type,
537 fold_build_pointer_plus ((*arglist)[2],
538 (*arglist)[1]),
539 build_int_cst (ptr_type_node, 0)),
540 (*arglist)[0]);
542 case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
543 return build_constructor_va (return_type, 2,
544 NULL_TREE, (*arglist)[0],
545 NULL_TREE, (*arglist)[1]);
546 default:
547 gcc_unreachable ();
551 /* invert result */
552 #define __VSTRING_FLAG_IN 8
553 /* result type */
554 #define __VSTRING_FLAG_RT 4
555 /* zero search */
556 #define __VSTRING_FLAG_ZS 2
557 /* set condition code */
558 #define __VSTRING_FLAG_CS 1
560 /* Return the flags value to be used for string low-level builtins
561 when expanded from overloaded builtin OB_FCODE. */
562 static unsigned int
563 s390_get_vstring_flags (int ob_fcode)
565 unsigned int flags = 0;
567 switch (ob_fcode)
569 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
570 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
571 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
572 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
573 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
574 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
575 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
576 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
577 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
578 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
579 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
580 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
581 flags |= __VSTRING_FLAG_IN;
582 break;
583 default:
584 break;
586 switch (ob_fcode)
589 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
590 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
591 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
592 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
593 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
594 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
595 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
596 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
597 flags |= __VSTRING_FLAG_RT;
598 break;
599 default:
600 break;
602 switch (ob_fcode)
605 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
606 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
607 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
608 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
609 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
610 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
611 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
612 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
613 flags |= __VSTRING_FLAG_ZS;
614 break;
615 default:
616 break;
618 switch (ob_fcode)
620 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
621 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
622 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
623 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
624 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
625 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
626 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
627 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
628 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
629 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
630 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
631 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
632 flags |= __VSTRING_FLAG_CS;
633 break;
634 default:
635 break;
637 return flags;
639 #undef __VSTRING_FLAG_IN
640 #undef __VSTRING_FLAG_RT
641 #undef __VSTRING_FLAG_ZS
642 #undef __VSTRING_FLAG_CS
644 /* For several overloaded builtins the argument lists do not match
645 exactly the signature of a low-level builtin. This function
646 adjusts the argument list ARGLIST for the overloaded builtin
647 OB_FCODE to the signature of the low-level builtin given by
648 DECL. */
649 static void
650 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
651 vec<tree, va_gc> **arglist)
653 tree arg_chain;
654 int src_arg_index, dest_arg_index;
655 vec<tree, va_gc> *folded_args = NULL;
657 /* We at most add one more operand to the list. */
658 vec_alloc (folded_args, (*arglist)->allocated () + 1);
659 for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
660 src_arg_index = 0, dest_arg_index = 0;
661 !VOID_TYPE_P (TREE_VALUE (arg_chain));
662 arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
664 bool arg_assigned_p = false;
665 switch (ob_fcode)
667 /* For all these the low level builtin needs an additional flags parameter. */
668 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
669 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
670 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
671 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
672 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
673 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
674 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
675 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
676 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
677 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
678 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
679 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
680 if (dest_arg_index == 2)
682 folded_args->quick_push (build_int_cst (integer_type_node,
683 s390_get_vstring_flags (ob_fcode)));
684 arg_assigned_p = true;
686 break;
687 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
688 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
689 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
690 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
691 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
692 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
693 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
694 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
695 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
696 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
697 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
698 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
699 if (dest_arg_index == 3)
701 folded_args->quick_push (build_int_cst (integer_type_node,
702 s390_get_vstring_flags (ob_fcode)));
703 arg_assigned_p = true;
705 break;
706 case S390_OVERLOADED_BUILTIN_s390_vec_sel:
707 case S390_OVERLOADED_BUILTIN_s390_vec_insert:
708 case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
709 case S390_OVERLOADED_BUILTIN_s390_vec_load_len_r:
710 /* Swap the first to arguments. It is better to do it here
711 instead of the header file to avoid operand checking
712 throwing error messages for a weird operand index. */
713 if (dest_arg_index < 2)
715 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
716 (**arglist)[1 - dest_arg_index]));
717 src_arg_index++;
718 arg_assigned_p = true;
720 break;
721 case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
722 case S390_OVERLOADED_BUILTIN_s390_vec_store_len_r:
723 if (dest_arg_index == 1 || dest_arg_index == 2)
725 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
726 (**arglist)[3 - dest_arg_index]));
727 src_arg_index++;
728 arg_assigned_p = true;
730 break;
732 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
734 int code;
735 if (dest_arg_index == 1)
737 tree arg = (**arglist)[src_arg_index];
739 if (TREE_CODE (arg) != INTEGER_CST)
741 error ("constant value required for builtin %qF argument %d",
742 decl, src_arg_index + 1);
743 return;
746 switch (tree_to_uhwi (arg))
748 case 64: code = 0; break;
749 case 128: code = 1; break;
750 case 256: code = 2; break;
751 case 512: code = 3; break;
752 case 1024: code = 4; break;
753 case 2048: code = 5; break;
754 case 4096: code = 6; break;
755 default:
756 error ("valid values for builtin %qF argument %d are 64, "
757 "128, 256, 512, 1024, 2048, and 4096", decl,
758 src_arg_index + 1);
759 return;
761 folded_args->quick_push (build_int_cst (integer_type_node,
762 code));
763 src_arg_index++;
764 arg_assigned_p = true;
767 break;
768 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
769 /* Duplicate the first src arg. */
770 if (dest_arg_index == 0)
772 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
773 (**arglist)[src_arg_index]));
774 arg_assigned_p = true;
776 break;
777 default:
778 break;
780 if (!arg_assigned_p)
782 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
783 (**arglist)[src_arg_index]));
784 src_arg_index++;
787 *arglist = folded_args;
790 /* Check whether the arguments in ARGLIST match the function type
791 DEF_TYPE. Return the number of argument types which required
792 conversion/promotion in order to make it match.
793 0 stands for a perfect match - all operand types match without changes
794 INT_MAX stands for a mismatch. */
795 static int
796 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
797 vec<tree, va_gc> *arglist)
799 unsigned int i;
800 int match_type = 0;
802 for (i = 0; i < vec_safe_length (arglist); i++)
804 tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
805 tree in_arg = (*arglist)[i];
806 tree in_type = TREE_TYPE (in_arg);
808 if (in_type == error_mark_node)
809 goto mismatch;
811 if (VECTOR_TYPE_P (b_arg_type))
813 /* Vector types have to match precisely. */
814 if (b_arg_type != in_type
815 && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
816 goto mismatch;
819 if (lang_hooks.types_compatible_p (in_type, b_arg_type))
820 continue;
822 if (lang_hooks.types_compatible_p (
823 lang_hooks.types.type_promotes_to (in_type),
824 lang_hooks.types.type_promotes_to (b_arg_type)))
826 match_type++;
827 continue;
830 /* In this stage the C++ frontend would go ahead trying to find
831 implicit conversion chains for the argument to match the
832 target type. We will mimic this here only for our limited
833 subset of argument types. */
834 if (TREE_CODE (b_arg_type) == INTEGER_TYPE
835 && TREE_CODE (in_type) == INTEGER_TYPE)
837 match_type++;
838 continue;
841 /* If the incoming pointer argument has more qualifiers than the
842 argument type it can still be an imperfect match. */
843 if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
844 && !(TYPE_QUALS (TREE_TYPE (in_type))
845 & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
846 && (TYPE_QUALS (TREE_TYPE (b_arg_type))
847 & ~TYPE_QUALS (TREE_TYPE (in_type))))
849 tree qual_in_type =
850 build_qualified_type (TREE_TYPE (in_type),
851 TYPE_QUALS (TREE_TYPE (b_arg_type)));
853 if (lang_hooks.types_compatible_p (qual_in_type,
854 TREE_TYPE (b_arg_type)))
856 match_type++;
857 continue;
861 mismatch:
862 if (TARGET_DEBUG_ARG)
864 fprintf (stderr, " mismatch in operand: %d incoming: ", i + 1);
865 print_generic_expr (stderr, in_type, TDF_VOPS|TDF_MEMSYMS);
866 fprintf (stderr, " expected: ");
867 print_generic_expr (stderr, b_arg_type, TDF_VOPS|TDF_MEMSYMS);
868 fprintf (stderr, "\n");
870 return INT_MAX;
873 return match_type;
876 /* Return the number of elements in the vector arguments of FNDECL in
877 case all it matches for all vector arguments, -1 otherwise. */
878 static int
879 s390_vec_n_elem (tree fndecl)
881 tree b_arg_chain;
882 int n_elem = -1;
884 if (VECTOR_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
885 n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
887 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
888 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
889 b_arg_chain = TREE_CHAIN (b_arg_chain))
891 int tmp_n_elem;
892 if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
893 continue;
894 tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
895 if (n_elem != -1 && n_elem != tmp_n_elem)
896 return -1;
897 n_elem = tmp_n_elem;
899 return n_elem;
903 /* Return a tree expression for a call to the overloaded builtin
904 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
905 tree
906 s390_resolve_overloaded_builtin (location_t loc, tree ob_fndecl,
907 void *passed_arglist, bool)
909 vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
910 unsigned int in_args_num = vec_safe_length (arglist);
911 unsigned int ob_args_num = 0;
912 unsigned int ob_fcode = DECL_MD_FUNCTION_CODE (ob_fndecl);
913 enum s390_overloaded_builtin_vars bindex;
914 unsigned int i;
915 int last_match_type = INT_MAX;
916 int last_match_index = -1;
917 unsigned int all_op_flags;
918 const unsigned int ob_flags = bflags_for_builtin(ob_fcode);
919 int num_matches = 0;
920 tree target_builtin_decl, b_arg_chain, return_type;
921 enum s390_builtin_ov_type_index last_match_fntype_index = BT_OV_MAX;
923 if (TARGET_DEBUG_ARG)
924 fprintf (stderr,
925 "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
926 (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
927 ob_fcode < S390_BUILTIN_MAX ? "not" : "");
929 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
930 if (ob_fcode < S390_BUILTIN_MAX)
932 if (ob_flags & B_INT)
934 error_at (loc,
935 "builtin %qF is for GCC internal use only",
936 ob_fndecl);
937 return error_mark_node;
939 return NULL_TREE;
942 if (ob_flags & B_DEP)
943 warning_at (loc, 0, "builtin %qF is deprecated", ob_fndecl);
945 if (!TARGET_VX && (ob_flags & B_VX))
947 error_at (loc, "%qF requires %<-mvx%>", ob_fndecl);
948 return error_mark_node;
951 if (!TARGET_VXE && (ob_flags & B_VXE))
953 error_at (loc, "%qF requires z14 or higher", ob_fndecl);
954 return error_mark_node;
957 if (!TARGET_VXE2 && (ob_flags & B_VXE2))
959 error_at (loc, "%qF requires z15 or higher", ob_fndecl);
960 return error_mark_node;
963 if (!TARGET_VXE3 && (ob_flags & B_VXE3))
965 error_at (loc, "%qF requires arch15 or higher", ob_fndecl);
966 return error_mark_node;
969 ob_fcode -= S390_BUILTIN_MAX;
971 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
972 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
973 b_arg_chain = TREE_CHAIN (b_arg_chain))
974 ob_args_num++;
976 if (ob_args_num != in_args_num)
978 error_at (loc,
979 "mismatch in number of arguments for builtin %qF. "
980 "Expected: %d got %d", ob_fndecl,
981 ob_args_num, in_args_num);
982 return error_mark_node;
985 for (i = 0; i < in_args_num; i++)
986 if ((*arglist)[i] == error_mark_node)
987 return error_mark_node;
989 /* Overloaded builtins without any variants are directly expanded here. */
990 if (desc_start_for_overloaded_builtin[ob_fcode] ==
991 S390_OVERLOADED_BUILTIN_VAR_MAX)
992 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
994 for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
995 bindex <= desc_end_for_overloaded_builtin[ob_fcode];
996 bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
998 int match_type;
999 enum s390_builtin_ov_type_index type_index =
1000 type_for_overloaded_builtin_var[bindex];
1002 if (TARGET_DEBUG_ARG)
1003 fprintf (stderr, "checking variant number: %d", (int)bindex);
1005 match_type = s390_fn_types_compatible (type_index, arglist);
1007 if (match_type == INT_MAX)
1008 continue;
1010 if (TARGET_DEBUG_ARG)
1011 fprintf (stderr,
1012 " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
1013 match_type);
1015 if (match_type < last_match_type)
1017 num_matches = 1;
1018 last_match_type = match_type;
1019 last_match_fntype_index = type_index;
1020 last_match_index = bindex;
1022 else if (match_type == last_match_type)
1023 num_matches++;
1026 if (last_match_type == INT_MAX)
1028 error_at (loc, "invalid parameter combination for intrinsic %qs",
1029 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1030 return error_mark_node;
1032 else if (num_matches > 1)
1034 error_at (loc, "ambiguous overload for intrinsic %qs",
1035 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1036 return error_mark_node;
1039 if (!TARGET_VXE
1040 && bflags_overloaded_builtin_var[last_match_index] & B_VXE)
1042 error_at (loc, "%qs matching variant requires z14 or higher",
1043 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1044 return error_mark_node;
1048 if (!TARGET_VXE2
1049 && bflags_overloaded_builtin_var[last_match_index] & B_VXE2)
1051 error_at (loc, "%qs matching variant requires z15 or higher",
1052 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1053 return error_mark_node;
1056 if (!TARGET_VXE3
1057 && bflags_overloaded_builtin_var[last_match_index] & B_VXE3)
1059 error_at (loc, "%qs matching variant requires arch15 or higher",
1060 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1061 return error_mark_node;
1064 if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
1065 warning_at (loc, 0, "%qs matching variant is deprecated",
1066 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1068 /* Overloaded variants which have MAX set as low level builtin are
1069 supposed to be replaced during expansion with something else. */
1070 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1071 target_builtin_decl = ob_fndecl;
1072 else
1073 target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
1075 all_op_flags = opflags_overloaded_builtin_var[last_match_index];
1076 return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
1078 /* Check for the operand flags in the overloaded builtin variant. */
1079 for (i = 0; i < ob_args_num; i++)
1081 unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
1082 tree arg = (*arglist)[i];
1083 tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
1085 all_op_flags = all_op_flags >> O_SHIFT;
1087 if (op_flags == O_ELEM)
1089 int n_elem = s390_vec_n_elem (target_builtin_decl);
1090 gcc_assert (n_elem > 0);
1091 gcc_assert (type == integer_type_node);
1092 (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
1093 fold_convert (integer_type_node, arg),
1094 build_int_cst (NULL_TREE, n_elem - 1));
1097 if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
1098 continue;
1100 if ((TYPE_UNSIGNED (type)
1101 && !int_fits_type_p (arg, c_common_unsigned_type (type)))
1102 || (!TYPE_UNSIGNED (type)
1103 && !int_fits_type_p (arg, c_common_signed_type (type))))
1105 error("constant argument %d for builtin %qF is out "
1106 "of range for target type",
1107 i + 1, target_builtin_decl);
1108 return error_mark_node;
1111 if (TREE_CODE (arg) == INTEGER_CST
1112 && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
1113 return error_mark_node;
1116 /* Handle builtins we expand directly - without mapping it to a low
1117 level builtin. */
1118 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1119 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
1121 s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
1123 if (VOID_TYPE_P (return_type))
1124 return build_function_call_vec (loc, vNULL, target_builtin_decl,
1125 arglist, NULL);
1126 else
1127 return fully_fold_convert (return_type,
1128 build_function_call_vec (loc, vNULL, target_builtin_decl,
1129 arglist, NULL));
1132 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
1133 void
1134 s390_register_target_pragmas (void)
1136 targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
1137 #if S390_USE_TARGET_ATTRIBUTE
1138 /* Update pragma hook to allow parsing #pragma GCC target. */
1139 targetm.target_option.pragma_parse = s390_pragma_target_parse;
1140 #endif