libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / config / s390 / s390-c.cc
blob4521a86f0480a047168c563cdb44bdbd750da2ab
1 /* Language specific subroutines used for code generation on IBM S/390
2 and zSeries
3 Copyright (C) 2015-2024 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 /* Called to decide whether a conditional macro should be expanded.
178 Since we have exactly one such macro (i.e, 'vector'), we do not
179 need to examine the 'tok' parameter. */
181 static cpp_hashnode *
182 s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
184 cpp_hashnode *expand_this = tok->val.node.node;
185 cpp_hashnode *ident;
186 static bool expand_bool_p = false;
187 int idx = 0;
188 enum rid rid_code;
190 /* The vector keyword is only expanded if the machine actually
191 provides hardware support. */
192 if (!TARGET_ZVECTOR)
193 return NULL;
195 ident = s390_categorize_keyword (tok);
197 /* Triggered when we picked a different variant in
198 s390_categorize_keyword. */
199 if (ident != expand_this)
200 expand_this = NULL;
202 /* The vector keyword has been found already and we remembered to
203 expand the next bool. */
204 if (expand_bool_p && ident == C_CPP_HASHNODE (__bool_keyword))
206 expand_bool_p = false;
207 return ident;
210 if (ident != C_CPP_HASHNODE (__vector_keyword))
211 return expand_this;
214 tok = cpp_peek_token (pfile, idx++);
215 while (tok->type == CPP_PADDING);
216 ident = s390_categorize_keyword (tok);
218 if (!ident)
219 return expand_this;
221 /* vector bool - remember to expand the next bool. */
222 if (ident == C_CPP_HASHNODE (__bool_keyword))
224 expand_bool_p = true;
225 return C_CPP_HASHNODE (__vector_keyword);
228 /* The boost libraries have code with Iterator::vector vector in it.
229 If we allow the normal handling, this module will be called
230 recursively, and the vector will be skipped.; */
231 if (ident == C_CPP_HASHNODE (__vector_keyword))
232 return expand_this;
234 rid_code = (enum rid)(ident->rid_code);
236 if (cpp_macro_p (ident))
238 /* Now actually fetch the tokens we "peeked" before and do a
239 lookahead for the next. */
241 (void) cpp_get_token (pfile);
242 while (--idx > 0);
244 tok = cpp_peek_token (pfile, idx++);
245 while (tok->type == CPP_PADDING);
246 ident = s390_categorize_keyword (tok);
248 if (ident == C_CPP_HASHNODE (__bool_keyword))
250 expand_bool_p = true;
251 return C_CPP_HASHNODE (__vector_keyword);
253 else if (ident)
254 rid_code = (enum rid)(ident->rid_code);
257 /* vector keyword followed by type identifier: vector unsigned,
258 vector long, ...
259 Types consisting of more than one identifier are not supported by
260 zvector e.g. long long, long double, unsigned long int. */
261 if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
262 || rid_code == RID_SHORT || rid_code == RID_SIGNED
263 || rid_code == RID_INT || rid_code == RID_CHAR
264 || (rid_code == RID_FLOAT && TARGET_VXE)
265 || rid_code == RID_DOUBLE)
267 expand_this = C_CPP_HASHNODE (__vector_keyword);
268 /* If the next keyword is bool, it will need to be expanded as
269 well. */
271 tok = cpp_peek_token (pfile, idx++);
272 while (tok->type == CPP_PADDING);
273 ident = s390_categorize_keyword (tok);
275 /* __vector long __bool a; */
276 if (ident == C_CPP_HASHNODE (__bool_keyword))
277 expand_bool_p = true;
279 /* If there are more tokens to check. */
280 else if (ident)
282 /* Triggered with: __vector long long __bool a; */
284 tok = cpp_peek_token (pfile, idx++);
285 while (tok->type == CPP_PADDING);
286 ident = s390_categorize_keyword (tok);
288 if (ident == C_CPP_HASHNODE (__bool_keyword))
289 expand_bool_p = true;
293 return expand_this;
296 /* Helper function that defines or undefines macros. If SET is true, the macro
297 MACRO_DEF is defined. If SET is false, the macro MACRO_UNDEF is undefined.
298 Nothing is done if SET and WAS_SET have the same value. */
299 template <typename F>
300 static void
301 s390_def_or_undef_macro (cpp_reader *pfile, F is_set,
302 const struct cl_target_option *old_opts,
303 const struct cl_target_option *new_opts,
304 const char *macro_def, const char *macro_undef)
306 bool was_set;
307 bool set;
309 was_set = (!old_opts) ? false : is_set (old_opts);
310 set = is_set (new_opts);
311 if (was_set == set)
312 return;
313 if (set)
314 cpp_define (pfile, macro_def);
315 else
316 cpp_undef (pfile, macro_undef);
319 struct target_flag_set_p
321 target_flag_set_p (unsigned int mask) : m_mask (mask) {}
323 bool
324 operator() (const struct cl_target_option *opts) const
326 return opts->x_target_flags & m_mask;
329 unsigned int m_mask;
332 /* Internal function to either define or undef the appropriate system
333 macros. */
334 static void
335 s390_cpu_cpp_builtins_internal (cpp_reader *pfile,
336 struct cl_target_option *opts,
337 const struct cl_target_option *old_opts)
339 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_OPT_HTM), old_opts,
340 opts, "__HTM__", "__HTM__");
341 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_OPT_VX), old_opts,
342 opts, "__VX__", "__VX__");
343 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR), old_opts,
344 opts, "__VEC__=10304", "__VEC__");
345 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR), old_opts,
346 opts, "__vector=__attribute__((vector_size(16)))",
347 "__vector__");
348 s390_def_or_undef_macro (
349 pfile, target_flag_set_p (MASK_ZVECTOR), old_opts, opts,
350 "__bool=__attribute__((s390_vector_bool)) unsigned", "__bool");
352 char macro_def[64];
353 gcc_assert (s390_arch != PROCESSOR_NATIVE);
354 sprintf (macro_def, "__ARCH__=%d", processor_table[s390_arch].arch_level);
355 cpp_undef (pfile, "__ARCH__");
356 cpp_define (pfile, macro_def);
358 s390_def_or_undef_macro (
359 pfile,
360 [] (const struct cl_target_option *opts) { return TARGET_VXE_P (opts); },
361 old_opts, opts, "__LONG_DOUBLE_VX__", "__LONG_DOUBLE_VX__");
363 if (!flag_iso)
365 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
366 old_opts, opts, "__VECTOR_KEYWORD_SUPPORTED__",
367 "__VECTOR_KEYWORD_SUPPORTED__");
368 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
369 old_opts, opts, "vector=vector", "vector");
370 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
371 old_opts, opts, "bool=bool", "bool");
372 s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
373 old_opts, opts, "_Bool=_Bool", "_Bool");
374 if (TARGET_ZVECTOR_P (opts->x_target_flags) && __vector_keyword == NULL)
376 __vector_keyword = get_identifier ("__vector");
377 C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
379 vector_keyword = get_identifier ("vector");
380 C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
382 __bool_keyword = get_identifier ("__bool");
383 C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
385 bool_keyword = get_identifier ("bool");
386 C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
388 _Bool_keyword = get_identifier ("_Bool");
389 C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
391 /* Enable context-sensitive macros. */
392 cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
397 /* Define platform dependent macros. */
398 void
399 s390_cpu_cpp_builtins (cpp_reader *pfile)
401 struct cl_target_option opts;
403 cpp_assert (pfile, "cpu=s390");
404 cpp_assert (pfile, "machine=s390");
405 cpp_define (pfile, "__s390__");
406 if (TARGET_ZARCH)
407 cpp_define (pfile, "__zarch__");
408 if (TARGET_64BIT)
409 cpp_define (pfile, "__s390x__");
410 if (TARGET_LONG_DOUBLE_128)
411 cpp_define (pfile, "__LONG_DOUBLE_128__");
412 cl_target_option_save (&opts, &global_options, &global_options_set);
413 s390_cpu_cpp_builtins_internal (pfile, &opts, NULL);
414 cpp_define (pfile, "__GCC_ASM_FLAG_OUTPUTS__");
417 #if S390_USE_TARGET_ATTRIBUTE
418 /* Hook to validate the current #pragma GCC target and set the state, and
419 update the macros based on what was changed. If ARGS is NULL, then
420 POP_TARGET is used to reset the options. */
422 static bool
423 s390_pragma_target_parse (tree args, tree pop_target)
425 tree prev_tree = build_target_option_node (&global_options,
426 &global_options_set);
427 tree cur_tree;
429 if (! args)
430 cur_tree = pop_target;
431 else
433 cur_tree = s390_valid_target_attribute_tree (args, &global_options,
434 &global_options_set, true);
435 if (!cur_tree || cur_tree == error_mark_node)
437 cl_target_option_restore (&global_options, &global_options_set,
438 TREE_TARGET_OPTION (prev_tree));
439 return false;
443 target_option_current_node = cur_tree;
444 s390_activate_target_options (target_option_current_node);
447 struct cl_target_option *prev_opt;
448 struct cl_target_option *cur_opt;
450 /* Figure out the previous/current differences. */
451 prev_opt = TREE_TARGET_OPTION (prev_tree);
452 cur_opt = TREE_TARGET_OPTION (cur_tree);
454 /* For the definitions, ensure all newly defined macros are considered
455 as used for -Wunused-macros. There is no point warning about the
456 compiler predefined macros. */
457 cpp_options *cpp_opts = cpp_get_options (parse_in);
458 unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
460 cpp_opts->warn_unused_macros = 0;
462 /* Define all of the macros for new options that were just turned on. */
463 cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
464 s390_cpu_cpp_builtins_internal (parse_in, cur_opt, prev_opt);
465 cpp_stop_forcing_token_locations (parse_in);
467 cpp_opts->warn_unused_macros = saved_warn_unused_macros;
470 return true;
472 #endif
474 /* Expand builtins which can directly be mapped to tree expressions.
475 LOC - location information
476 FCODE - function code of the builtin
477 ARGLIST - value supposed to be passed as arguments
478 RETURN-TYPE - expected return type of the builtin */
479 static tree
480 s390_expand_overloaded_builtin (location_t loc,
481 unsigned fcode,
482 vec<tree, va_gc> *arglist,
483 tree return_type)
485 switch (fcode)
487 case S390_OVERLOADED_BUILTIN_s390_vec_step:
488 if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
490 error_at (loc, "builtin %qs can only be used on vector types",
491 "vec_step");
492 return error_mark_node;
494 return build_int_cst (NULL_TREE,
495 TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
496 case S390_OVERLOADED_BUILTIN_s390_vec_xl:
497 case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
498 case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
500 /* Build a vector type with the alignment of the source
501 location in order to enable correct alignment hints to be
502 generated for vl. */
503 unsigned align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[1])));
504 tree mem_type = build_aligned_type (return_type, align);
505 return build2 (MEM_REF, mem_type,
506 fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
507 build_int_cst (ptr_type_node, 0));
509 case S390_OVERLOADED_BUILTIN_s390_vec_xst:
510 case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
511 case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
513 /* Build a vector type with the alignment of the target
514 location in order to enable correct alignment hints to be
515 generated for vst. */
516 unsigned align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[2])));
517 tree mem_type = build_aligned_type (TREE_TYPE ((*arglist)[0]), align);
518 return build2 (MODIFY_EXPR, mem_type,
519 build2 (MEM_REF, mem_type,
520 fold_build_pointer_plus ((*arglist)[2],
521 (*arglist)[1]),
522 build_int_cst (ptr_type_node, 0)),
523 (*arglist)[0]);
525 case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
526 return build_constructor_va (return_type, 2,
527 NULL_TREE, (*arglist)[0],
528 NULL_TREE, (*arglist)[1]);
529 default:
530 gcc_unreachable ();
534 /* invert result */
535 #define __VSTRING_FLAG_IN 8
536 /* result type */
537 #define __VSTRING_FLAG_RT 4
538 /* zero search */
539 #define __VSTRING_FLAG_ZS 2
540 /* set condition code */
541 #define __VSTRING_FLAG_CS 1
543 /* Return the flags value to be used for string low-level builtins
544 when expanded from overloaded builtin OB_FCODE. */
545 static unsigned int
546 s390_get_vstring_flags (int ob_fcode)
548 unsigned int flags = 0;
550 switch (ob_fcode)
552 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
553 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
554 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
555 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
556 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
557 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
558 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
559 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
560 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
561 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
562 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
563 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
564 flags |= __VSTRING_FLAG_IN;
565 break;
566 default:
567 break;
569 switch (ob_fcode)
572 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
573 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
574 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
575 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
576 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
577 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
578 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
579 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
580 flags |= __VSTRING_FLAG_RT;
581 break;
582 default:
583 break;
585 switch (ob_fcode)
588 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
589 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
590 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
591 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
592 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
593 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
594 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
595 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
596 flags |= __VSTRING_FLAG_ZS;
597 break;
598 default:
599 break;
601 switch (ob_fcode)
603 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
604 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
605 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
606 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
607 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
608 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
609 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
610 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
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 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
614 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
615 flags |= __VSTRING_FLAG_CS;
616 break;
617 default:
618 break;
620 return flags;
622 #undef __VSTRING_FLAG_IN
623 #undef __VSTRING_FLAG_RT
624 #undef __VSTRING_FLAG_ZS
625 #undef __VSTRING_FLAG_CS
627 /* For several overloaded builtins the argument lists do not match
628 exactly the signature of a low-level builtin. This function
629 adjusts the argument list ARGLIST for the overloaded builtin
630 OB_FCODE to the signature of the low-level builtin given by
631 DECL. */
632 static void
633 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
634 vec<tree, va_gc> **arglist)
636 tree arg_chain;
637 int src_arg_index, dest_arg_index;
638 vec<tree, va_gc> *folded_args = NULL;
640 /* We at most add one more operand to the list. */
641 vec_alloc (folded_args, (*arglist)->allocated () + 1);
642 for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
643 src_arg_index = 0, dest_arg_index = 0;
644 !VOID_TYPE_P (TREE_VALUE (arg_chain));
645 arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
647 bool arg_assigned_p = false;
648 switch (ob_fcode)
650 /* For all these the low level builtin needs an additional flags parameter. */
651 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
652 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
653 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
654 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
655 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
656 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
657 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
658 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
659 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
660 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
661 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
662 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
663 if (dest_arg_index == 2)
665 folded_args->quick_push (build_int_cst (integer_type_node,
666 s390_get_vstring_flags (ob_fcode)));
667 arg_assigned_p = true;
669 break;
670 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
671 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
672 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
673 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
674 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
675 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
676 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
677 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
678 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
679 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
680 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
681 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
682 if (dest_arg_index == 3)
684 folded_args->quick_push (build_int_cst (integer_type_node,
685 s390_get_vstring_flags (ob_fcode)));
686 arg_assigned_p = true;
688 break;
689 case S390_OVERLOADED_BUILTIN_s390_vec_sel:
690 case S390_OVERLOADED_BUILTIN_s390_vec_insert:
691 case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
692 /* Swap the first to arguments. It is better to do it here
693 instead of the header file to avoid operand checking
694 throwing error messages for a weird operand index. */
695 if (dest_arg_index < 2)
697 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
698 (**arglist)[1 - dest_arg_index]));
699 src_arg_index++;
700 arg_assigned_p = true;
702 break;
703 case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
704 if (dest_arg_index == 1 || dest_arg_index == 2)
706 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
707 (**arglist)[3 - dest_arg_index]));
708 src_arg_index++;
709 arg_assigned_p = true;
711 break;
713 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
715 int code;
716 if (dest_arg_index == 1)
718 tree arg = (**arglist)[src_arg_index];
720 if (TREE_CODE (arg) != INTEGER_CST)
722 error ("constant value required for builtin %qF argument %d",
723 decl, src_arg_index + 1);
724 return;
727 switch (tree_to_uhwi (arg))
729 case 64: code = 0; break;
730 case 128: code = 1; break;
731 case 256: code = 2; break;
732 case 512: code = 3; break;
733 case 1024: code = 4; break;
734 case 2048: code = 5; break;
735 case 4096: code = 6; break;
736 default:
737 error ("valid values for builtin %qF argument %d are 64, "
738 "128, 256, 512, 1024, 2048, and 4096", decl,
739 src_arg_index + 1);
740 return;
742 folded_args->quick_push (build_int_cst (integer_type_node,
743 code));
744 src_arg_index++;
745 arg_assigned_p = true;
748 break;
749 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
750 /* Duplicate the first src arg. */
751 if (dest_arg_index == 0)
753 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
754 (**arglist)[src_arg_index]));
755 arg_assigned_p = true;
757 break;
758 default:
759 break;
761 if (!arg_assigned_p)
763 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
764 (**arglist)[src_arg_index]));
765 src_arg_index++;
768 *arglist = folded_args;
771 /* Check whether the arguments in ARGLIST match the function type
772 DEF_TYPE. Return the number of argument types which required
773 conversion/promotion in order to make it match.
774 0 stands for a perfect match - all operand types match without changes
775 INT_MAX stands for a mismatch. */
776 static int
777 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
778 vec<tree, va_gc> *arglist)
780 unsigned int i;
781 int match_type = 0;
783 for (i = 0; i < vec_safe_length (arglist); i++)
785 tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
786 tree in_arg = (*arglist)[i];
787 tree in_type = TREE_TYPE (in_arg);
789 if (in_type == error_mark_node)
790 goto mismatch;
792 if (VECTOR_TYPE_P (b_arg_type))
794 /* Vector types have to match precisely. */
795 if (b_arg_type != in_type
796 && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
797 goto mismatch;
800 if (lang_hooks.types_compatible_p (in_type, b_arg_type))
801 continue;
803 if (lang_hooks.types_compatible_p (
804 lang_hooks.types.type_promotes_to (in_type),
805 lang_hooks.types.type_promotes_to (b_arg_type)))
807 match_type++;
808 continue;
811 /* In this stage the C++ frontend would go ahead trying to find
812 implicit conversion chains for the argument to match the
813 target type. We will mimic this here only for our limited
814 subset of argument types. */
815 if (TREE_CODE (b_arg_type) == INTEGER_TYPE
816 && TREE_CODE (in_type) == INTEGER_TYPE)
818 match_type++;
819 continue;
822 /* If the incoming pointer argument has more qualifiers than the
823 argument type it can still be an imperfect match. */
824 if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
825 && !(TYPE_QUALS (TREE_TYPE (in_type))
826 & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
827 && (TYPE_QUALS (TREE_TYPE (b_arg_type))
828 & ~TYPE_QUALS (TREE_TYPE (in_type))))
830 tree qual_in_type =
831 build_qualified_type (TREE_TYPE (in_type),
832 TYPE_QUALS (TREE_TYPE (b_arg_type)));
834 if (lang_hooks.types_compatible_p (qual_in_type,
835 TREE_TYPE (b_arg_type)))
837 match_type++;
838 continue;
842 mismatch:
843 if (TARGET_DEBUG_ARG)
845 fprintf (stderr, " mismatch in operand: %d incoming: ", i + 1);
846 print_generic_expr (stderr, in_type, TDF_VOPS|TDF_MEMSYMS);
847 fprintf (stderr, " expected: ");
848 print_generic_expr (stderr, b_arg_type, TDF_VOPS|TDF_MEMSYMS);
849 fprintf (stderr, "\n");
851 return INT_MAX;
854 return match_type;
857 /* Return the number of elements in the vector arguments of FNDECL in
858 case all it matches for all vector arguments, -1 otherwise. */
859 static int
860 s390_vec_n_elem (tree fndecl)
862 tree b_arg_chain;
863 int n_elem = -1;
865 if (VECTOR_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
866 n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
868 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
869 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
870 b_arg_chain = TREE_CHAIN (b_arg_chain))
872 int tmp_n_elem;
873 if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
874 continue;
875 tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
876 if (n_elem != -1 && n_elem != tmp_n_elem)
877 return -1;
878 n_elem = tmp_n_elem;
880 return n_elem;
884 /* Return a tree expression for a call to the overloaded builtin
885 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
886 tree
887 s390_resolve_overloaded_builtin (location_t loc,
888 tree ob_fndecl,
889 void *passed_arglist)
891 vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
892 unsigned int in_args_num = vec_safe_length (arglist);
893 unsigned int ob_args_num = 0;
894 unsigned int ob_fcode = DECL_MD_FUNCTION_CODE (ob_fndecl);
895 enum s390_overloaded_builtin_vars bindex;
896 unsigned int i;
897 int last_match_type = INT_MAX;
898 int last_match_index = -1;
899 unsigned int all_op_flags;
900 const unsigned int ob_flags = bflags_for_builtin(ob_fcode);
901 int num_matches = 0;
902 tree target_builtin_decl, b_arg_chain, return_type;
903 enum s390_builtin_ov_type_index last_match_fntype_index = BT_OV_MAX;
905 if (TARGET_DEBUG_ARG)
906 fprintf (stderr,
907 "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
908 (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
909 ob_fcode < S390_BUILTIN_MAX ? "not" : "");
911 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
912 if (ob_fcode < S390_BUILTIN_MAX)
914 if (ob_flags & B_INT)
916 error_at (loc,
917 "builtin %qF is for GCC internal use only",
918 ob_fndecl);
919 return error_mark_node;
921 return NULL_TREE;
924 if (ob_flags & B_DEP)
925 warning_at (loc, 0, "builtin %qF is deprecated", ob_fndecl);
927 if (!TARGET_VX && (ob_flags & B_VX))
929 error_at (loc, "%qF requires %<-mvx%>", ob_fndecl);
930 return error_mark_node;
933 if (!TARGET_VXE && (ob_flags & B_VXE))
935 error_at (loc, "%qF requires z14 or higher", ob_fndecl);
936 return error_mark_node;
939 if (!TARGET_VXE2 && (ob_flags & B_VXE2))
941 error_at (loc, "%qF requires z15 or higher", ob_fndecl);
942 return error_mark_node;
945 ob_fcode -= S390_BUILTIN_MAX;
947 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
948 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
949 b_arg_chain = TREE_CHAIN (b_arg_chain))
950 ob_args_num++;
952 if (ob_args_num != in_args_num)
954 error_at (loc,
955 "mismatch in number of arguments for builtin %qF. "
956 "Expected: %d got %d", ob_fndecl,
957 ob_args_num, in_args_num);
958 return error_mark_node;
961 for (i = 0; i < in_args_num; i++)
962 if ((*arglist)[i] == error_mark_node)
963 return error_mark_node;
965 /* Overloaded builtins without any variants are directly expanded here. */
966 if (desc_start_for_overloaded_builtin[ob_fcode] ==
967 S390_OVERLOADED_BUILTIN_VAR_MAX)
968 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
970 for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
971 bindex <= desc_end_for_overloaded_builtin[ob_fcode];
972 bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
974 int match_type;
975 enum s390_builtin_ov_type_index type_index =
976 type_for_overloaded_builtin_var[bindex];
978 if (TARGET_DEBUG_ARG)
979 fprintf (stderr, "checking variant number: %d", (int)bindex);
981 match_type = s390_fn_types_compatible (type_index, arglist);
983 if (match_type == INT_MAX)
984 continue;
986 if (TARGET_DEBUG_ARG)
987 fprintf (stderr,
988 " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
989 match_type);
991 if (match_type < last_match_type)
993 num_matches = 1;
994 last_match_type = match_type;
995 last_match_fntype_index = type_index;
996 last_match_index = bindex;
998 else if (match_type == last_match_type)
999 num_matches++;
1002 if (last_match_type == INT_MAX)
1004 error_at (loc, "invalid parameter combination for intrinsic %qs",
1005 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1006 return error_mark_node;
1008 else if (num_matches > 1)
1010 error_at (loc, "ambiguous overload for intrinsic %qs",
1011 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1012 return error_mark_node;
1015 if (!TARGET_VXE
1016 && bflags_overloaded_builtin_var[last_match_index] & B_VXE)
1018 error_at (loc, "%qs matching variant requires z14 or higher",
1019 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1020 return error_mark_node;
1024 if (!TARGET_VXE2
1025 && bflags_overloaded_builtin_var[last_match_index] & B_VXE2)
1027 error_at (loc, "%qs matching variant requires z15 or higher",
1028 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1029 return error_mark_node;
1032 if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
1033 warning_at (loc, 0, "%qs matching variant is deprecated",
1034 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1036 /* Overloaded variants which have MAX set as low level builtin are
1037 supposed to be replaced during expansion with something else. */
1038 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1039 target_builtin_decl = ob_fndecl;
1040 else
1041 target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
1043 all_op_flags = opflags_overloaded_builtin_var[last_match_index];
1044 return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
1046 /* Check for the operand flags in the overloaded builtin variant. */
1047 for (i = 0; i < ob_args_num; i++)
1049 unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
1050 tree arg = (*arglist)[i];
1051 tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
1053 all_op_flags = all_op_flags >> O_SHIFT;
1055 if (op_flags == O_ELEM)
1057 int n_elem = s390_vec_n_elem (target_builtin_decl);
1058 gcc_assert (n_elem > 0);
1059 gcc_assert (type == integer_type_node);
1060 (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
1061 fold_convert (integer_type_node, arg),
1062 build_int_cst (NULL_TREE, n_elem - 1));
1065 if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
1066 continue;
1068 if ((TYPE_UNSIGNED (type)
1069 && !int_fits_type_p (arg, c_common_unsigned_type (type)))
1070 || (!TYPE_UNSIGNED (type)
1071 && !int_fits_type_p (arg, c_common_signed_type (type))))
1073 error("constant argument %d for builtin %qF is out "
1074 "of range for target type",
1075 i + 1, target_builtin_decl);
1076 return error_mark_node;
1079 if (TREE_CODE (arg) == INTEGER_CST
1080 && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
1081 return error_mark_node;
1084 /* Handle builtins we expand directly - without mapping it to a low
1085 level builtin. */
1086 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1087 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
1089 s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
1091 if (VOID_TYPE_P (return_type))
1092 return build_function_call_vec (loc, vNULL, target_builtin_decl,
1093 arglist, NULL);
1094 else
1095 return fully_fold_convert (return_type,
1096 build_function_call_vec (loc, vNULL, target_builtin_decl,
1097 arglist, NULL));
1100 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
1101 void
1102 s390_register_target_pragmas (void)
1104 targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
1105 #if S390_USE_TARGET_ATTRIBUTE
1106 /* Update pragma hook to allow parsing #pragma GCC target. */
1107 targetm.target_option.pragma_parse = s390_pragma_target_parse;
1108 #endif