1 /* Language specific subroutines used for code generation on IBM S/390
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)
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
34 #include "coretypes.h"
37 #include "c-family/c-common.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
58 static enum s390_builtin_ov_type_index
59 type_for_overloaded_builtin_var
[S390_OVERLOADED_BUILTIN_VAR_MAX
+ 1] =
66 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, OPFLAGS, FNTYPE) FNTYPE,
67 #include "s390-builtins.def"
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] =
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] =
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
] =
110 #undef DEF_POINTER_TYPE
111 #undef DEF_DISTINCT_TYPE
112 #undef DEF_VECTOR_TYPE
113 #undef DEF_OPAQUE_VECTOR_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
] = {
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). */
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
);
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
);
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
;
186 static bool expand_bool_p
= false;
190 /* The vector keyword is only expanded if the machine actually
191 provides hardware support. */
195 ident
= s390_categorize_keyword (tok
);
197 /* Triggered when we picked a different variant in
198 s390_categorize_keyword. */
199 if (ident
!= expand_this
)
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;
210 if (ident
!= C_CPP_HASHNODE (__vector_keyword
))
214 tok
= cpp_peek_token (pfile
, idx
++);
215 while (tok
->type
== CPP_PADDING
);
216 ident
= s390_categorize_keyword (tok
);
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
))
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
);
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
);
254 rid_code
= (enum rid
)(ident
->rid_code
);
257 /* vector keyword followed by type identifier: vector unsigned,
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
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. */
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;
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
>
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
)
309 was_set
= (!old_opts
) ? false : is_set (old_opts
);
310 set
= is_set (new_opts
);
314 cpp_define (pfile
, macro_def
);
316 cpp_undef (pfile
, macro_undef
);
319 struct target_flag_set_p
321 target_flag_set_p (unsigned int mask
) : m_mask (mask
) {}
324 operator() (const struct cl_target_option
*opts
) const
326 return opts
->x_target_flags
& m_mask
;
332 /* Internal function to either define or undef the appropriate system
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)))",
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");
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 (
360 [] (const struct cl_target_option
*opts
) { return TARGET_VXE_P (opts
); },
361 old_opts
, opts
, "__LONG_DOUBLE_VX__", "__LONG_DOUBLE_VX__");
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. */
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__");
407 cpp_define (pfile
, "__zarch__");
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. */
423 s390_pragma_target_parse (tree args
, tree pop_target
)
425 tree prev_tree
= build_target_option_node (&global_options
,
426 &global_options_set
);
430 cur_tree
= pop_target
;
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
));
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
;
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 */
480 s390_expand_overloaded_builtin (location_t loc
,
482 vec
<tree
, va_gc
> *arglist
,
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",
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
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],
522 build_int_cst (ptr_type_node
, 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]);
535 #define __VSTRING_FLAG_IN 8
537 #define __VSTRING_FLAG_RT 4
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. */
546 s390_get_vstring_flags (int ob_fcode
)
548 unsigned int flags
= 0;
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
;
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
;
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
;
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
;
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
633 s390_adjust_builtin_arglist (unsigned int ob_fcode
, tree decl
,
634 vec
<tree
, va_gc
> **arglist
)
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;
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;
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;
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
]));
700 arg_assigned_p
= true;
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
]));
709 arg_assigned_p
= true;
713 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry
:
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);
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;
737 error ("valid values for builtin %qF argument %d are 64, "
738 "128, 256, 512, 1024, 2048, and 4096", decl
,
742 folded_args
->quick_push (build_int_cst (integer_type_node
,
745 arg_assigned_p
= true;
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;
763 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
764 (**arglist
)[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. */
777 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex
,
778 vec
<tree
, va_gc
> *arglist
)
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
)
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
))
800 if (lang_hooks
.types_compatible_p (in_type
, b_arg_type
))
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
)))
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
)
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
))))
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
)))
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");
857 /* Return the number of elements in the vector arguments of FNDECL in
858 case all it matches for all vector arguments, -1 otherwise. */
860 s390_vec_n_elem (tree fndecl
)
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
))
873 if (TREE_CODE (TREE_VALUE (b_arg_chain
)) != VECTOR_TYPE
)
875 tmp_n_elem
= TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain
));
876 if (n_elem
!= -1 && n_elem
!= tmp_n_elem
)
884 /* Return a tree expression for a call to the overloaded builtin
885 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
887 s390_resolve_overloaded_builtin (location_t loc
,
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
;
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
);
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
)
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
)
917 "builtin %qF is for GCC internal use only",
919 return error_mark_node
;
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
))
952 if (ob_args_num
!= in_args_num
)
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))
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
)
986 if (TARGET_DEBUG_ARG
)
988 " %s match score: %d\n", match_type
== 0 ? "perfect" : "imperfect",
991 if (match_type
< last_match_type
)
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
)
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
;
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
;
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
;
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
))
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
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
,
1095 return fully_fold_convert (return_type
,
1096 build_function_call_vec (loc
, vNULL
, target_builtin_decl
,
1100 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
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
;