1 /* Language specific subroutines used for code generation on IBM S/390
3 Copyright (C) 2015-2017 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.c.
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. */
32 #include "coretypes.h"
35 #include "c-family/c-common.h"
39 #include "stringpool.h"
40 #include "c-family/c-pragma.h"
41 #include "langhooks.h"
42 #include "tree-pretty-print.h"
44 #include "s390-builtins.h"
46 static GTY(()) tree __vector_keyword
;
47 static GTY(()) tree vector_keyword
;
48 static GTY(()) tree __bool_keyword
;
49 static GTY(()) tree bool_keyword
;
50 static GTY(()) tree _Bool_keyword
;
53 /* Generate an array holding all the descriptions of variants of
54 overloaded builtins defined with OB_DEF_VAR in
56 static enum s390_builtin_ov_type_index
57 type_for_overloaded_builtin_var
[S390_OVERLOADED_BUILTIN_VAR_MAX
+ 1] =
64 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, FNTYPE) FNTYPE,
65 #include "s390-builtins.def"
70 /* Generate an array indexed by an overloaded builtin index returning
71 the first index in desc_for_overloaded_builtin_var where the
72 variants for the builtin can be found. */
73 static enum s390_overloaded_builtin_vars
74 desc_start_for_overloaded_builtin
[S390_OVERLOADED_BUILTIN_MAX
+ 1] =
80 #define OB_DEF(NAME, FIRST_VAR_NAME,...) \
81 S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
82 #define OB_DEF_VAR(...)
83 #include "s390-builtins.def"
84 S390_OVERLOADED_BUILTIN_VAR_MAX
87 /* Generate an array indexed by an overloaded builtin index returning
88 the last index in desc_for_overloaded_builtin_var where the
89 variants for the builtin can be found. */
90 static enum s390_overloaded_builtin_vars
91 desc_end_for_overloaded_builtin
[S390_OVERLOADED_BUILTIN_MAX
+ 1] =
97 #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...) \
98 S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
99 #define OB_DEF_VAR(...)
100 #include "s390-builtins.def"
101 S390_OVERLOADED_BUILTIN_VAR_MAX
104 static enum s390_builtin_type_index
105 s390_builtin_ov_types
[BT_OV_MAX
][MAX_OV_OPERANDS
] =
108 #undef DEF_POINTER_TYPE
109 #undef DEF_DISTINCT_TYPE
110 #undef DEF_VECTOR_TYPE
111 #undef DEF_OPAQUE_VECTOR_TYPE
114 #define DEF_TYPE(...)
115 #define DEF_POINTER_TYPE(...)
116 #define DEF_DISTINCT_TYPE(...)
117 #define DEF_VECTOR_TYPE(...)
118 #define DEF_OPAQUE_VECTOR_TYPE(...)
119 #define DEF_FN_TYPE(...)
120 #define DEF_OV_TYPE(INDEX, args...) { args },
121 #include "s390-builtin-types.def"
124 static const enum s390_builtins
125 bt_for_overloaded_builtin_var
[S390_OVERLOADED_BUILTIN_VAR_MAX
] = {
131 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
133 #include "s390-builtins.def"
136 /* In addition to calling fold_convert for EXPR of type TYPE, also
137 call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
138 hiding there (PR47197). */
140 fully_fold_convert (tree type
, tree expr
)
142 tree result
= fold_convert (type
, expr
);
143 bool maybe_const
= true;
145 if (!c_dialect_cxx ())
146 result
= c_fully_fold (result
, false, &maybe_const
);
151 /* Unify the different variants to the same nodes in order to keep the
152 code working with it simple. */
153 static cpp_hashnode
*
154 s390_categorize_keyword (const cpp_token
*tok
)
156 if (tok
->type
== CPP_NAME
)
158 cpp_hashnode
*ident
= tok
->val
.node
.node
;
160 if (ident
== C_CPP_HASHNODE (vector_keyword
))
161 return C_CPP_HASHNODE (__vector_keyword
);
163 if (ident
== C_CPP_HASHNODE (bool_keyword
))
164 return C_CPP_HASHNODE (__bool_keyword
);
166 if (ident
== C_CPP_HASHNODE (_Bool_keyword
))
167 return C_CPP_HASHNODE (__bool_keyword
);
175 /* Called to decide whether a conditional macro should be expanded.
176 Since we have exactly one such macro (i.e, 'vector'), we do not
177 need to examine the 'tok' parameter. */
179 static cpp_hashnode
*
180 s390_macro_to_expand (cpp_reader
*pfile
, const cpp_token
*tok
)
182 cpp_hashnode
*expand_this
= tok
->val
.node
.node
;
184 static bool expand_bool_p
= false;
188 /* The vector keyword is only expanded if the machine actually
189 provides hardware support. */
193 ident
= s390_categorize_keyword (tok
);
195 /* Triggered when we picked a different variant in
196 s390_categorize_keyword. */
197 if (ident
!= expand_this
)
200 /* The vector keyword has been found already and we remembered to
201 expand the next bool. */
202 if (expand_bool_p
&& ident
== C_CPP_HASHNODE (__bool_keyword
))
204 expand_bool_p
= false;
208 if (ident
!= C_CPP_HASHNODE (__vector_keyword
))
212 tok
= cpp_peek_token (pfile
, idx
++);
213 while (tok
->type
== CPP_PADDING
);
214 ident
= s390_categorize_keyword (tok
);
219 /* vector bool - remember to expand the next bool. */
220 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
222 expand_bool_p
= true;
223 return C_CPP_HASHNODE (__vector_keyword
);
226 /* The boost libraries have code with Iterator::vector vector in it.
227 If we allow the normal handling, this module will be called
228 recursively, and the vector will be skipped.; */
229 if (ident
== C_CPP_HASHNODE (__vector_keyword
))
232 rid_code
= (enum rid
)(ident
->rid_code
);
234 if (ident
->type
== NT_MACRO
)
236 /* Now actually fetch the tokens we "peeked" before and do a
237 lookahead for the next. */
239 (void) cpp_get_token (pfile
);
242 tok
= cpp_peek_token (pfile
, idx
++);
243 while (tok
->type
== CPP_PADDING
);
244 ident
= s390_categorize_keyword (tok
);
246 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
248 expand_bool_p
= true;
249 return C_CPP_HASHNODE (__vector_keyword
);
252 rid_code
= (enum rid
)(ident
->rid_code
);
255 /* vector keyword followed by type identifier: vector unsigned,
257 Types consisting of more than one identifier are not supported by
258 zvector e.g. long long, long double, unsigned long int. */
259 if (rid_code
== RID_UNSIGNED
|| rid_code
== RID_LONG
260 || rid_code
== RID_SHORT
|| rid_code
== RID_SIGNED
261 || rid_code
== RID_INT
|| rid_code
== RID_CHAR
262 || rid_code
== RID_DOUBLE
)
264 expand_this
= C_CPP_HASHNODE (__vector_keyword
);
265 /* If the next keyword is bool, it will need to be expanded as
268 tok
= cpp_peek_token (pfile
, idx
++);
269 while (tok
->type
== CPP_PADDING
);
270 ident
= s390_categorize_keyword (tok
);
272 /* __vector long __bool a; */
273 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
274 expand_bool_p
= true;
277 /* Triggered with: __vector long long __bool a; */
279 tok
= cpp_peek_token (pfile
, idx
++);
280 while (tok
->type
== CPP_PADDING
);
281 ident
= s390_categorize_keyword (tok
);
283 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
284 expand_bool_p
= true;
291 /* Helper function that defines or undefines macros. If SET is true, the macro
292 MACRO_DEF is defined. If SET is false, the macro MACRO_UNDEF is undefined.
293 Nothing is done if SET and WAS_SET have the same value. */
295 s390_def_or_undef_macro (cpp_reader
*pfile
,
297 const struct cl_target_option
*old_opts
,
298 const struct cl_target_option
*new_opts
,
299 const char *macro_def
, const char *macro_undef
)
304 was_set
= (!old_opts
) ? false : old_opts
->x_target_flags
& mask
;
305 set
= new_opts
->x_target_flags
& mask
;
309 cpp_define (pfile
, macro_def
);
311 cpp_undef (pfile
, macro_undef
);
314 /* Internal function to either define or undef the appropriate system
317 s390_cpu_cpp_builtins_internal (cpp_reader
*pfile
,
318 struct cl_target_option
*opts
,
319 const struct cl_target_option
*old_opts
)
321 s390_def_or_undef_macro (pfile
, MASK_OPT_HTM
, old_opts
, opts
,
322 "__HTM__", "__HTM__");
323 s390_def_or_undef_macro (pfile
, MASK_OPT_VX
, old_opts
, opts
,
324 "__S390_VX__", "__S390_VX__");
325 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
326 "__VEC__=10301", "__VEC__");
327 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
328 "__vector=__attribute__((vector_size(16)))",
330 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
331 "__bool=__attribute__((s390_vector_bool)) unsigned",
336 gcc_assert (s390_arch
!= PROCESSOR_NATIVE
);
337 arch_level
= (int)s390_arch
+ 3;
338 if (s390_arch
>= PROCESSOR_2094_Z9_EC
)
339 /* Z9_EC has the same level as Z9_109. */
341 /* Review when a new arch is added and increase the value. */
342 char dummy
[23 - 2 * PROCESSOR_max
] __attribute__((unused
));
343 sprintf (macro_def
, "__ARCH__=%d", arch_level
);
344 cpp_undef (pfile
, "__ARCH__");
345 cpp_define (pfile
, macro_def
);
350 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
351 "__VECTOR_KEYWORD_SUPPORTED__",
352 "__VECTOR_KEYWORD_SUPPORTED__");
353 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
354 "vector=vector", "vector");
355 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
356 "bool=bool", "bool");
357 if (TARGET_ZVECTOR_P (opts
->x_target_flags
) && __vector_keyword
== NULL
)
359 __vector_keyword
= get_identifier ("__vector");
360 C_CPP_HASHNODE (__vector_keyword
)->flags
|= NODE_CONDITIONAL
;
362 vector_keyword
= get_identifier ("vector");
363 C_CPP_HASHNODE (vector_keyword
)->flags
|= NODE_CONDITIONAL
;
365 __bool_keyword
= get_identifier ("__bool");
366 C_CPP_HASHNODE (__bool_keyword
)->flags
|= NODE_CONDITIONAL
;
368 bool_keyword
= get_identifier ("bool");
369 C_CPP_HASHNODE (bool_keyword
)->flags
|= NODE_CONDITIONAL
;
371 _Bool_keyword
= get_identifier ("_Bool");
372 C_CPP_HASHNODE (_Bool_keyword
)->flags
|= NODE_CONDITIONAL
;
374 /* Enable context-sensitive macros. */
375 cpp_get_callbacks (pfile
)->macro_to_expand
= s390_macro_to_expand
;
380 /* Define platform dependent macros. */
382 s390_cpu_cpp_builtins (cpp_reader
*pfile
)
384 struct cl_target_option opts
;
386 cpp_assert (pfile
, "cpu=s390");
387 cpp_assert (pfile
, "machine=s390");
388 cpp_define (pfile
, "__s390__");
390 cpp_define (pfile
, "__zarch__");
392 cpp_define (pfile
, "__s390x__");
393 if (TARGET_LONG_DOUBLE_128
)
394 cpp_define (pfile
, "__LONG_DOUBLE_128__");
395 cl_target_option_save (&opts
, &global_options
);
396 s390_cpu_cpp_builtins_internal (pfile
, &opts
, NULL
);
399 #if S390_USE_TARGET_ATTRIBUTE
400 /* Hook to validate the current #pragma GCC target and set the state, and
401 update the macros based on what was changed. If ARGS is NULL, then
402 POP_TARGET is used to reset the options. */
405 s390_pragma_target_parse (tree args
, tree pop_target
)
407 tree prev_tree
= build_target_option_node (&global_options
);
411 cur_tree
= pop_target
;
414 cur_tree
= s390_valid_target_attribute_tree (args
, &global_options
,
415 &global_options_set
, true);
416 if (!cur_tree
|| cur_tree
== error_mark_node
)
418 cl_target_option_restore (&global_options
,
419 TREE_TARGET_OPTION (prev_tree
));
424 target_option_current_node
= cur_tree
;
425 s390_activate_target_options (target_option_current_node
);
428 struct cl_target_option
*prev_opt
;
429 struct cl_target_option
*cur_opt
;
431 /* Figure out the previous/current differences. */
432 prev_opt
= TREE_TARGET_OPTION (prev_tree
);
433 cur_opt
= TREE_TARGET_OPTION (cur_tree
);
435 /* For the definitions, ensure all newly defined macros are considered
436 as used for -Wunused-macros. There is no point warning about the
437 compiler predefined macros. */
438 cpp_options
*cpp_opts
= cpp_get_options (parse_in
);
439 unsigned char saved_warn_unused_macros
= cpp_opts
->warn_unused_macros
;
441 cpp_opts
->warn_unused_macros
= 0;
443 /* Define all of the macros for new options that were just turned on. */
444 s390_cpu_cpp_builtins_internal (parse_in
, cur_opt
, prev_opt
);
446 cpp_opts
->warn_unused_macros
= saved_warn_unused_macros
;
453 /* Expand builtins which can directly be mapped to tree expressions.
454 LOC - location information
455 FCODE - function code of the builtin
456 ARGLIST - value supposed to be passed as arguments
457 RETURN-TYPE - expected return type of the builtin */
459 s390_expand_overloaded_builtin (location_t loc
,
461 vec
<tree
, va_gc
> *arglist
,
466 case S390_OVERLOADED_BUILTIN_s390_vec_step
:
467 if (TREE_CODE (TREE_TYPE ((*arglist
)[0])) != VECTOR_TYPE
)
469 error_at (loc
, "builtin vec_step can only be used on vector types.");
470 return error_mark_node
;
472 return build_int_cst (NULL_TREE
,
473 TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist
)[0])));
474 case S390_OVERLOADED_BUILTIN_s390_vec_xld2
:
475 case S390_OVERLOADED_BUILTIN_s390_vec_xlw4
:
476 return build2 (MEM_REF
, return_type
,
477 fold_build_pointer_plus ((*arglist
)[1], (*arglist
)[0]),
478 build_int_cst (TREE_TYPE ((*arglist
)[1]), 0));
479 case S390_OVERLOADED_BUILTIN_s390_vec_xstd2
:
480 case S390_OVERLOADED_BUILTIN_s390_vec_xstw4
:
481 return build2 (MODIFY_EXPR
, TREE_TYPE((*arglist
)[0]),
482 build1 (INDIRECT_REF
, TREE_TYPE((*arglist
)[0]),
483 fold_build_pointer_plus ((*arglist
)[2], (*arglist
)[1])),
485 case S390_OVERLOADED_BUILTIN_s390_vec_load_pair
:
486 return build_constructor_va (return_type
, 2,
487 NULL_TREE
, (*arglist
)[0],
488 NULL_TREE
, (*arglist
)[1]);
495 #define __VSTRING_FLAG_IN 8
497 #define __VSTRING_FLAG_RT 4
499 #define __VSTRING_FLAG_ZS 2
500 /* set condition code */
501 #define __VSTRING_FLAG_CS 1
503 /* Return the flags value to be used for string low-level builtins
504 when expanded from overloaded builtin OB_FCODE. */
506 s390_get_vstring_flags (int ob_fcode
)
508 unsigned int flags
= 0;
512 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx
:
513 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx
:
514 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne
:
515 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc
:
516 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
517 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
518 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx
:
519 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx
:
520 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg
:
521 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc
:
522 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
523 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
524 flags
|= __VSTRING_FLAG_IN
;
532 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq
:
533 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne
:
534 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc
:
535 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
536 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg
:
537 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg
:
538 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc
:
539 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
540 flags
|= __VSTRING_FLAG_RT
;
548 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx
:
549 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx
:
550 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc
:
551 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
552 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx
:
553 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx
:
554 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc
:
555 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
556 flags
|= __VSTRING_FLAG_ZS
;
563 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc
:
564 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc
:
565 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc
:
566 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
567 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc
:
568 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
569 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc
:
570 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc
:
571 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc
:
572 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
573 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc
:
574 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
575 flags
|= __VSTRING_FLAG_CS
;
582 #undef __VSTRING_FLAG_IN
583 #undef __VSTRING_FLAG_RT
584 #undef __VSTRING_FLAG_ZS
585 #undef __VSTRING_FLAG_CS
587 /* For several overloaded builtins the argument lists do not match
588 exactly the signature of a low-level builtin. This function
589 adjusts the argument list ARGLIST for the overloaded builtin
590 OB_FCODE to the signature of the low-level builtin given by
593 s390_adjust_builtin_arglist (unsigned int ob_fcode
, tree decl
,
594 vec
<tree
, va_gc
> **arglist
)
597 int src_arg_index
, dest_arg_index
;
598 vec
<tree
, va_gc
> *folded_args
= NULL
;
600 /* We at most add one more operand to the list. */
601 vec_alloc (folded_args
, (*arglist
)->allocated () + 1);
602 for (arg_chain
= TYPE_ARG_TYPES (TREE_TYPE (decl
)),
603 src_arg_index
= 0, dest_arg_index
= 0;
604 !VOID_TYPE_P (TREE_VALUE (arg_chain
));
605 arg_chain
= TREE_CHAIN (arg_chain
), dest_arg_index
++)
607 bool arg_assigned_p
= false;
610 /* For all these the low level builtin needs an additional flags parameter. */
611 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx
:
612 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx
:
613 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx
:
614 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx
:
615 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq
:
616 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne
:
617 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc
:
618 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc
:
619 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc
:
620 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
621 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc
:
622 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
623 if (dest_arg_index
== 2)
625 folded_args
->quick_push (build_int_cst (integer_type_node
,
626 s390_get_vstring_flags (ob_fcode
)));
627 arg_assigned_p
= true;
630 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx
:
631 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx
:
632 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx
:
633 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx
:
634 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg
:
635 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg
:
636 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc
:
637 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc
:
638 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc
:
639 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
640 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc
:
641 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
642 if (dest_arg_index
== 3)
644 folded_args
->quick_push (build_int_cst (integer_type_node
,
645 s390_get_vstring_flags (ob_fcode
)));
646 arg_assigned_p
= true;
649 case S390_OVERLOADED_BUILTIN_s390_vec_sel
:
650 case S390_OVERLOADED_BUILTIN_s390_vec_insert
:
651 case S390_OVERLOADED_BUILTIN_s390_vec_load_len
:
652 /* Swap the first to arguments. It is better to do it here
653 instead of the header file to avoid operand checking
654 throwing error messages for a weird operand index. */
655 if (dest_arg_index
< 2)
657 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
658 (**arglist
)[1 - dest_arg_index
]));
660 arg_assigned_p
= true;
663 case S390_OVERLOADED_BUILTIN_s390_vec_store_len
:
664 if (dest_arg_index
== 1 || dest_arg_index
== 2)
666 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
667 (**arglist
)[3 - dest_arg_index
]));
669 arg_assigned_p
= true;
673 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry
:
677 if (dest_arg_index
== 1)
679 switch (tree_to_uhwi ((**arglist
)[src_arg_index
]))
681 case 64: code
= 0; break;
682 case 128: code
= 1; break;
683 case 256: code
= 2; break;
684 case 512: code
= 3; break;
685 case 1024: code
= 4; break;
686 case 2048: code
= 5; break;
687 case 4096: code
= 6; break;
689 error ("valid values for builtin %qF argument %d are 64, "
690 "128, 256, 512, 1024, 2048, and 4096", decl
,
694 folded_args
->quick_push (build_int_cst (integer_type_node
,
697 arg_assigned_p
= true;
701 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask
:
702 /* Duplicate the first src arg. */
703 if (dest_arg_index
== 0)
705 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
706 (**arglist
)[src_arg_index
]));
707 arg_assigned_p
= true;
715 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
716 (**arglist
)[src_arg_index
]));
720 *arglist
= folded_args
;
723 /* Check whether the arguments in ARGLIST match the function type
724 DEF_TYPE. Return the number of argument types which required
725 conversion/promotion in order to make it match.
726 0 stands for a perfect match - all operand types match without changes
727 INT_MAX stands for a mismatch. */
729 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex
,
730 vec
<tree
, va_gc
> *arglist
)
735 for (i
= 0; i
< vec_safe_length (arglist
); i
++)
737 tree b_arg_type
= s390_builtin_types
[s390_builtin_ov_types
[typeindex
][i
+ 1]];
738 tree in_arg
= (*arglist
)[i
];
739 tree in_type
= TREE_TYPE (in_arg
);
741 if (TREE_CODE (b_arg_type
) == VECTOR_TYPE
)
743 /* Vector types have to match precisely. */
744 if (b_arg_type
!= in_type
745 && TYPE_MAIN_VARIANT (b_arg_type
) != TYPE_MAIN_VARIANT (in_type
))
749 if (lang_hooks
.types_compatible_p (in_type
, b_arg_type
))
752 if (lang_hooks
.types_compatible_p (
753 lang_hooks
.types
.type_promotes_to (in_type
),
754 lang_hooks
.types
.type_promotes_to (b_arg_type
)))
760 /* In this stage the C++ frontend would go ahead trying to find
761 implicit conversion chains for the argument to match the
762 target type. We will mimic this here only for our limited
763 subset of argument types. */
764 if (TREE_CODE (b_arg_type
) == INTEGER_TYPE
765 && TREE_CODE (in_type
) == INTEGER_TYPE
)
771 /* If the incoming pointer argument has more qualifiers than the
772 argument type it can still be an imperfect match. */
773 if (POINTER_TYPE_P (b_arg_type
) && POINTER_TYPE_P (in_type
)
774 && !(TYPE_QUALS (TREE_TYPE (in_type
))
775 & ~TYPE_QUALS (TREE_TYPE (b_arg_type
)))
776 && (TYPE_QUALS (TREE_TYPE (b_arg_type
))
777 & ~TYPE_QUALS (TREE_TYPE (in_type
))))
780 build_qualified_type (TREE_TYPE (in_type
),
781 TYPE_QUALS (TREE_TYPE (b_arg_type
)));
783 if (lang_hooks
.types_compatible_p (qual_in_type
,
784 TREE_TYPE (b_arg_type
)))
792 if (TARGET_DEBUG_ARG
)
793 fprintf (stderr
, " mismatch in operand: %d\n", i
+ 1);
800 /* Return the number of elements in the vector arguments of FNDECL in
801 case all it matches for all vector arguments, -1 otherwise. */
803 s390_vec_n_elem (tree fndecl
)
808 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) == VECTOR_TYPE
)
809 n_elem
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl
))));
811 for (b_arg_chain
= TYPE_ARG_TYPES (TREE_TYPE (fndecl
));
812 !VOID_TYPE_P (TREE_VALUE (b_arg_chain
));
813 b_arg_chain
= TREE_CHAIN (b_arg_chain
))
816 if (TREE_CODE (TREE_VALUE (b_arg_chain
)) != VECTOR_TYPE
)
818 tmp_n_elem
= TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain
));
819 if (n_elem
!= -1 && n_elem
!= tmp_n_elem
)
827 /* Return a tree expression for a call to the overloaded builtin
828 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
830 s390_resolve_overloaded_builtin (location_t loc
,
832 void *passed_arglist
)
834 vec
<tree
, va_gc
> *arglist
= static_cast<vec
<tree
, va_gc
> *> (passed_arglist
);
835 unsigned int in_args_num
= vec_safe_length (arglist
);
836 unsigned int ob_args_num
= 0;
837 unsigned int ob_fcode
= DECL_FUNCTION_CODE (ob_fndecl
);
838 enum s390_overloaded_builtin_vars bindex
;
840 int last_match_type
= INT_MAX
;
841 int last_match_index
= -1;
842 unsigned int all_op_flags
;
844 tree target_builtin_decl
, b_arg_chain
, return_type
;
845 enum s390_builtin_ov_type_index last_match_fntype_index
;
847 if (TARGET_DEBUG_ARG
)
849 "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
850 (int)ob_fcode
, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl
)),
851 ob_fcode
< S390_BUILTIN_MAX
? "not" : "");
853 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
854 if (ob_fcode
< S390_BUILTIN_MAX
)
856 if (bflags_for_builtin(ob_fcode
) & B_INT
)
859 "builtin %qF is for GCC internal use only.",
861 return error_mark_node
;
866 ob_fcode
-= S390_BUILTIN_MAX
;
868 for (b_arg_chain
= TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl
));
869 !VOID_TYPE_P (TREE_VALUE (b_arg_chain
));
870 b_arg_chain
= TREE_CHAIN (b_arg_chain
))
873 if (ob_args_num
!= in_args_num
)
876 "mismatch in number of arguments for builtin %qF. "
877 "Expected: %d got %d", ob_fndecl
,
878 ob_args_num
, in_args_num
);
879 return error_mark_node
;
882 for (i
= 0; i
< in_args_num
; i
++)
883 if ((*arglist
)[i
] == error_mark_node
)
884 return error_mark_node
;
886 /* Overloaded builtins without any variants are directly expanded here. */
887 if (desc_start_for_overloaded_builtin
[ob_fcode
] ==
888 S390_OVERLOADED_BUILTIN_VAR_MAX
)
889 return s390_expand_overloaded_builtin (loc
, ob_fcode
, arglist
, NULL_TREE
);
891 for (bindex
= desc_start_for_overloaded_builtin
[ob_fcode
];
892 bindex
<= desc_end_for_overloaded_builtin
[ob_fcode
];
893 bindex
= (enum s390_overloaded_builtin_vars
)((int)bindex
+ 1))
896 enum s390_builtin_ov_type_index type_index
=
897 type_for_overloaded_builtin_var
[bindex
];
899 if (TARGET_DEBUG_ARG
)
900 fprintf (stderr
, "checking variant number: %d", (int)bindex
);
902 match_type
= s390_fn_types_compatible (type_index
, arglist
);
904 if (match_type
== INT_MAX
)
907 if (TARGET_DEBUG_ARG
)
909 " %s match score: %d\n", match_type
== 0 ? "perfect" : "imperfect",
912 if (match_type
< last_match_type
)
915 last_match_type
= match_type
;
916 last_match_fntype_index
= type_index
;
917 last_match_index
= bindex
;
919 else if (match_type
== last_match_type
)
923 if (last_match_type
== INT_MAX
)
925 error_at (loc
, "invalid parameter combination for intrinsic %qs",
926 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl
)));
927 return error_mark_node
;
929 else if (num_matches
> 1)
931 error_at (loc
, "ambiguous overload for intrinsic %qs",
932 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl
)));
933 return error_mark_node
;
936 if (bt_for_overloaded_builtin_var
[last_match_index
] == S390_BUILTIN_MAX
)
937 target_builtin_decl
= ob_fndecl
;
939 target_builtin_decl
= s390_builtin_decls
[bt_for_overloaded_builtin_var
[last_match_index
]];
941 all_op_flags
= opflags_overloaded_builtin_var
[last_match_index
];
942 return_type
= s390_builtin_types
[s390_builtin_ov_types
[last_match_fntype_index
][0]];
944 /* Check for the operand flags in the overloaded builtin variant. */
945 for (i
= 0; i
< ob_args_num
; i
++)
947 unsigned int op_flags
= all_op_flags
& ((1 << O_SHIFT
) - 1);
948 tree arg
= (*arglist
)[i
];
949 tree type
= s390_builtin_types
[s390_builtin_ov_types
[last_match_fntype_index
][i
+ 1]];
951 all_op_flags
= all_op_flags
>> O_SHIFT
;
953 if (op_flags
== O_ELEM
)
955 int n_elem
= s390_vec_n_elem (target_builtin_decl
);
956 gcc_assert (n_elem
> 0);
957 gcc_assert (type
== integer_type_node
);
958 (*arglist
)[i
] = build2 (BIT_AND_EXPR
, integer_type_node
,
959 fold_convert (integer_type_node
, arg
),
960 build_int_cst (NULL_TREE
, n_elem
- 1));
963 if (TREE_CODE (arg
) != INTEGER_CST
|| !O_IMM_P (op_flags
))
966 if ((TYPE_UNSIGNED (type
)
967 && !int_fits_type_p (arg
, c_common_unsigned_type (type
)))
968 || (!TYPE_UNSIGNED (type
)
969 && !int_fits_type_p (arg
, c_common_signed_type (type
))))
971 error("constant argument %d for builtin %qF is out "
972 "of range for target type",
973 i
+ 1, target_builtin_decl
);
974 return error_mark_node
;
977 if (TREE_CODE (arg
) == INTEGER_CST
978 && !s390_const_operand_ok (arg
, i
+ 1, op_flags
, target_builtin_decl
))
979 return error_mark_node
;
982 /* Handle builtins we expand directly - without mapping it to a low
984 if (bt_for_overloaded_builtin_var
[last_match_index
] == S390_BUILTIN_MAX
)
985 return s390_expand_overloaded_builtin (loc
, ob_fcode
, arglist
, return_type
);
987 s390_adjust_builtin_arglist (ob_fcode
, target_builtin_decl
, &arglist
);
989 if (VOID_TYPE_P (return_type
))
990 return build_function_call_vec (loc
, vNULL
, target_builtin_decl
,
993 return fully_fold_convert (return_type
,
994 build_function_call_vec (loc
, vNULL
, target_builtin_decl
,
998 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
1000 s390_register_target_pragmas (void)
1002 targetm
.resolve_overloaded_builtin
= s390_resolve_overloaded_builtin
;
1003 #if S390_USE_TARGET_ATTRIBUTE
1004 /* Update pragma hook to allow parsing #pragma GCC target. */
1005 targetm
.target_option
.pragma_parse
= s390_pragma_target_parse
;