1 /* Language specific subroutines used for code generation on IBM S/390
3 Copyright (C) 2015-2016 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"
38 #include "stringpool.h"
39 #include "c-family/c-pragma.h"
40 #include "langhooks.h"
41 #include "tree-pretty-print.h"
43 #include "s390-builtins.h"
45 static GTY(()) tree __vector_keyword
;
46 static GTY(()) tree vector_keyword
;
47 static GTY(()) tree __bool_keyword
;
48 static GTY(()) tree bool_keyword
;
49 static GTY(()) tree _Bool_keyword
;
52 /* Generate an array holding all the descriptions of variants of
53 overloaded builtins defined with OB_DEF_VAR in
55 static enum s390_builtin_ov_type_index
56 type_for_overloaded_builtin_var
[S390_OVERLOADED_BUILTIN_VAR_MAX
+ 1] =
63 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, FNTYPE) FNTYPE,
64 #include "s390-builtins.def"
69 /* Generate an array indexed by an overloaded builtin index returning
70 the first index in desc_for_overloaded_builtin_var where the
71 variants for the builtin can be found. */
72 static enum s390_overloaded_builtin_vars
73 desc_start_for_overloaded_builtin
[S390_OVERLOADED_BUILTIN_MAX
+ 1] =
79 #define OB_DEF(NAME, FIRST_VAR_NAME,...) \
80 S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
81 #define OB_DEF_VAR(...)
82 #include "s390-builtins.def"
83 S390_OVERLOADED_BUILTIN_VAR_MAX
86 /* Generate an array indexed by an overloaded builtin index returning
87 the last index in desc_for_overloaded_builtin_var where the
88 variants for the builtin can be found. */
89 static enum s390_overloaded_builtin_vars
90 desc_end_for_overloaded_builtin
[S390_OVERLOADED_BUILTIN_MAX
+ 1] =
96 #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...) \
97 S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
98 #define OB_DEF_VAR(...)
99 #include "s390-builtins.def"
100 S390_OVERLOADED_BUILTIN_VAR_MAX
103 static enum s390_builtin_type_index
104 s390_builtin_ov_types
[BT_OV_MAX
][MAX_OV_OPERANDS
] =
107 #undef DEF_POINTER_TYPE
108 #undef DEF_DISTINCT_TYPE
109 #undef DEF_VECTOR_TYPE
110 #undef DEF_OPAQUE_VECTOR_TYPE
113 #define DEF_TYPE(...)
114 #define DEF_POINTER_TYPE(...)
115 #define DEF_DISTINCT_TYPE(...)
116 #define DEF_VECTOR_TYPE(...)
117 #define DEF_OPAQUE_VECTOR_TYPE(...)
118 #define DEF_FN_TYPE(...)
119 #define DEF_OV_TYPE(INDEX, args...) { args },
120 #include "s390-builtin-types.def"
123 static const enum s390_builtins
124 bt_for_overloaded_builtin_var
[S390_OVERLOADED_BUILTIN_VAR_MAX
] = {
130 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
132 #include "s390-builtins.def"
135 /* In addition to calling fold_convert for EXPR of type TYPE, also
136 call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
137 hiding there (PR47197). */
139 fully_fold_convert (tree type
, tree expr
)
141 tree result
= fold_convert (type
, expr
);
142 bool maybe_const
= true;
144 if (!c_dialect_cxx ())
145 result
= c_fully_fold (result
, false, &maybe_const
);
150 /* Unify the different variants to the same nodes in order to keep the
151 code working with it simple. */
152 static cpp_hashnode
*
153 s390_categorize_keyword (const cpp_token
*tok
)
155 if (tok
->type
== CPP_NAME
)
157 cpp_hashnode
*ident
= tok
->val
.node
.node
;
159 if (ident
== C_CPP_HASHNODE (vector_keyword
))
160 return C_CPP_HASHNODE (__vector_keyword
);
162 if (ident
== C_CPP_HASHNODE (bool_keyword
))
163 return C_CPP_HASHNODE (__bool_keyword
);
165 if (ident
== C_CPP_HASHNODE (_Bool_keyword
))
166 return C_CPP_HASHNODE (__bool_keyword
);
174 /* Called to decide whether a conditional macro should be expanded.
175 Since we have exactly one such macro (i.e, 'vector'), we do not
176 need to examine the 'tok' parameter. */
178 static cpp_hashnode
*
179 s390_macro_to_expand (cpp_reader
*pfile
, const cpp_token
*tok
)
181 cpp_hashnode
*expand_this
= tok
->val
.node
.node
;
183 static bool expand_bool_p
= false;
187 /* The vector keyword is only expanded if the machine actually
188 provides hardware support. */
192 ident
= s390_categorize_keyword (tok
);
194 /* Triggered when we picked a different variant in
195 s390_categorize_keyword. */
196 if (ident
!= expand_this
)
199 /* The vector keyword has been found already and we remembered to
200 expand the next bool. */
201 if (expand_bool_p
&& ident
== C_CPP_HASHNODE (__bool_keyword
))
203 expand_bool_p
= false;
207 if (ident
!= C_CPP_HASHNODE (__vector_keyword
))
211 tok
= cpp_peek_token (pfile
, idx
++);
212 while (tok
->type
== CPP_PADDING
);
213 ident
= s390_categorize_keyword (tok
);
218 /* vector bool - remember to expand the next bool. */
219 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
221 expand_bool_p
= true;
222 return C_CPP_HASHNODE (__vector_keyword
);
225 /* The boost libraries have code with Iterator::vector vector in it.
226 If we allow the normal handling, this module will be called
227 recursively, and the vector will be skipped.; */
228 if (ident
== C_CPP_HASHNODE (__vector_keyword
))
231 rid_code
= (enum rid
)(ident
->rid_code
);
233 if (ident
->type
== NT_MACRO
)
235 /* Now actually fetch the tokens we "peeked" before and do a
236 lookahead for the next. */
238 (void) cpp_get_token (pfile
);
241 tok
= cpp_peek_token (pfile
, idx
++);
242 while (tok
->type
== CPP_PADDING
);
243 ident
= s390_categorize_keyword (tok
);
245 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
247 expand_bool_p
= true;
248 return C_CPP_HASHNODE (__vector_keyword
);
251 rid_code
= (enum rid
)(ident
->rid_code
);
254 /* vector keyword followed by type identifier: vector unsigned,
256 Types consisting of more than one identifier are not supported by
257 zvector e.g. long long, long double, unsigned long int. */
258 if (rid_code
== RID_UNSIGNED
|| rid_code
== RID_LONG
259 || rid_code
== RID_SHORT
|| rid_code
== RID_SIGNED
260 || rid_code
== RID_INT
|| rid_code
== RID_CHAR
261 || rid_code
== RID_DOUBLE
)
263 expand_this
= C_CPP_HASHNODE (__vector_keyword
);
264 /* If the next keyword is bool, it will need to be expanded as
267 tok
= cpp_peek_token (pfile
, idx
++);
268 while (tok
->type
== CPP_PADDING
);
269 ident
= s390_categorize_keyword (tok
);
271 /* __vector long __bool a; */
272 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
273 expand_bool_p
= true;
276 /* Triggered with: __vector long long __bool a; */
278 tok
= cpp_peek_token (pfile
, idx
++);
279 while (tok
->type
== CPP_PADDING
);
280 ident
= s390_categorize_keyword (tok
);
282 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
283 expand_bool_p
= true;
290 /* Helper function that defines or undefines macros. If SET is true, the macro
291 MACRO_DEF is defined. If SET is false, the macro MACRO_UNDEF is undefined.
292 Nothing is done if SET and WAS_SET have the same value. */
294 s390_def_or_undef_macro (cpp_reader
*pfile
,
296 const struct cl_target_option
*old_opts
,
297 const struct cl_target_option
*new_opts
,
298 const char *macro_def
, const char *macro_undef
)
303 was_set
= (!old_opts
) ? false : old_opts
->x_target_flags
& mask
;
304 set
= new_opts
->x_target_flags
& mask
;
308 cpp_define (pfile
, macro_def
);
310 cpp_undef (pfile
, macro_undef
);
313 /* Internal function to either define or undef the appropriate system
316 s390_cpu_cpp_builtins_internal (cpp_reader
*pfile
,
317 struct cl_target_option
*opts
,
318 const struct cl_target_option
*old_opts
)
320 s390_def_or_undef_macro (pfile
, MASK_OPT_HTM
, old_opts
, opts
,
321 "__HTM__", "__HTM__");
322 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
323 "__VEC__=10301", "__VEC__");
324 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
325 "__vector=__attribute__((vector_size(16)))",
327 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
328 "__bool=__attribute__((s390_vector_bool)) unsigned",
332 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
333 "__VECTOR_KEYWORD_SUPPORTED__",
334 "__VECTOR_KEYWORD_SUPPORTED__");
335 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
336 "vector=vector", "vector");
337 s390_def_or_undef_macro (pfile
, MASK_ZVECTOR
, old_opts
, opts
,
338 "bool=bool", "bool");
339 if (TARGET_ZVECTOR_P (opts
->x_target_flags
) && __vector_keyword
== NULL
)
341 __vector_keyword
= get_identifier ("__vector");
342 C_CPP_HASHNODE (__vector_keyword
)->flags
|= NODE_CONDITIONAL
;
344 vector_keyword
= get_identifier ("vector");
345 C_CPP_HASHNODE (vector_keyword
)->flags
|= NODE_CONDITIONAL
;
347 __bool_keyword
= get_identifier ("__bool");
348 C_CPP_HASHNODE (__bool_keyword
)->flags
|= NODE_CONDITIONAL
;
350 bool_keyword
= get_identifier ("bool");
351 C_CPP_HASHNODE (bool_keyword
)->flags
|= NODE_CONDITIONAL
;
353 _Bool_keyword
= get_identifier ("_Bool");
354 C_CPP_HASHNODE (_Bool_keyword
)->flags
|= NODE_CONDITIONAL
;
356 /* Enable context-sensitive macros. */
357 cpp_get_callbacks (pfile
)->macro_to_expand
= s390_macro_to_expand
;
362 /* Define platform dependent macros. */
364 s390_cpu_cpp_builtins (cpp_reader
*pfile
)
366 struct cl_target_option opts
;
368 cpp_assert (pfile
, "cpu=s390");
369 cpp_assert (pfile
, "machine=s390");
370 cpp_define (pfile
, "__s390__");
372 cpp_define (pfile
, "__zarch__");
374 cpp_define (pfile
, "__s390x__");
375 if (TARGET_LONG_DOUBLE_128
)
376 cpp_define (pfile
, "__LONG_DOUBLE_128__");
377 cl_target_option_save (&opts
, &global_options
);
378 s390_cpu_cpp_builtins_internal (pfile
, &opts
, NULL
);
381 #if S390_USE_TARGET_ATTRIBUTE
382 /* Hook to validate the current #pragma GCC target and set the state, and
383 update the macros based on what was changed. If ARGS is NULL, then
384 POP_TARGET is used to reset the options. */
387 s390_pragma_target_parse (tree args
, tree pop_target
)
389 tree prev_tree
= build_target_option_node (&global_options
);
393 cur_tree
= pop_target
;
396 cur_tree
= s390_valid_target_attribute_tree (args
, &global_options
,
397 &global_options_set
, true);
398 if (!cur_tree
|| cur_tree
== error_mark_node
)
400 cl_target_option_restore (&global_options
,
401 TREE_TARGET_OPTION (prev_tree
));
406 target_option_current_node
= cur_tree
;
407 s390_activate_target_options (target_option_current_node
);
410 struct cl_target_option
*prev_opt
;
411 struct cl_target_option
*cur_opt
;
413 /* Figure out the previous/current differences. */
414 prev_opt
= TREE_TARGET_OPTION (prev_tree
);
415 cur_opt
= TREE_TARGET_OPTION (cur_tree
);
417 /* For the definitions, ensure all newly defined macros are considered
418 as used for -Wunused-macros. There is no point warning about the
419 compiler predefined macros. */
420 cpp_options
*cpp_opts
= cpp_get_options (parse_in
);
421 unsigned char saved_warn_unused_macros
= cpp_opts
->warn_unused_macros
;
423 cpp_opts
->warn_unused_macros
= 0;
425 /* Define all of the macros for new options that were just turned on. */
426 s390_cpu_cpp_builtins_internal (parse_in
, cur_opt
, prev_opt
);
428 cpp_opts
->warn_unused_macros
= saved_warn_unused_macros
;
435 /* Expand builtins which can directly be mapped to tree expressions.
436 LOC - location information
437 FCODE - function code of the builtin
438 ARGLIST - value supposed to be passed as arguments
439 RETURN-TYPE - expected return type of the builtin */
441 s390_expand_overloaded_builtin (location_t loc
,
443 vec
<tree
, va_gc
> *arglist
,
448 case S390_OVERLOADED_BUILTIN_s390_vec_step
:
449 if (TREE_CODE (TREE_TYPE ((*arglist
)[0])) != VECTOR_TYPE
)
451 error_at (loc
, "Builtin vec_step can only be used on vector types.");
452 return error_mark_node
;
454 return build_int_cst (NULL_TREE
,
455 TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist
)[0])));
456 case S390_OVERLOADED_BUILTIN_s390_vec_xld2
:
457 case S390_OVERLOADED_BUILTIN_s390_vec_xlw4
:
458 return build2 (MEM_REF
, return_type
,
459 fold_build_pointer_plus ((*arglist
)[1], (*arglist
)[0]),
460 build_int_cst (TREE_TYPE ((*arglist
)[1]), 0));
461 case S390_OVERLOADED_BUILTIN_s390_vec_xstd2
:
462 case S390_OVERLOADED_BUILTIN_s390_vec_xstw4
:
463 return build2 (MODIFY_EXPR
, TREE_TYPE((*arglist
)[0]),
464 build1 (INDIRECT_REF
, TREE_TYPE((*arglist
)[0]),
465 fold_build_pointer_plus ((*arglist
)[2], (*arglist
)[1])),
467 case S390_OVERLOADED_BUILTIN_s390_vec_load_pair
:
468 return build_constructor_va (return_type
, 2,
469 NULL_TREE
, (*arglist
)[0],
470 NULL_TREE
, (*arglist
)[1]);
477 #define __VSTRING_FLAG_IN 8
479 #define __VSTRING_FLAG_RT 4
481 #define __VSTRING_FLAG_ZS 2
482 /* set condition code */
483 #define __VSTRING_FLAG_CS 1
485 /* Return the flags value to be used for string low-level builtins
486 when expanded from overloaded builtin OB_FCODE. */
488 s390_get_vstring_flags (int ob_fcode
)
490 unsigned int flags
= 0;
494 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx
:
495 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx
:
496 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne
:
497 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc
:
498 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
499 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
500 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx
:
501 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx
:
502 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg
:
503 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc
:
504 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
505 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
506 flags
|= __VSTRING_FLAG_IN
;
514 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq
:
515 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne
:
516 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc
:
517 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
518 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg
:
519 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg
:
520 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc
:
521 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
522 flags
|= __VSTRING_FLAG_RT
;
530 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx
:
531 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx
:
532 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc
:
533 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
534 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx
:
535 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx
:
536 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc
:
537 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
538 flags
|= __VSTRING_FLAG_ZS
;
545 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc
:
546 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc
:
547 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc
:
548 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
549 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc
:
550 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
551 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc
:
552 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc
:
553 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc
:
554 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
555 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc
:
556 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
557 flags
|= __VSTRING_FLAG_CS
;
564 #undef __VSTRING_FLAG_IN
565 #undef __VSTRING_FLAG_RT
566 #undef __VSTRING_FLAG_ZS
567 #undef __VSTRING_FLAG_CS
569 /* For several overloaded builtins the argument lists do not match
570 exactly the signature of a low-level builtin. This function
571 adjusts the argument list ARGLIST for the overloaded builtin
572 OB_FCODE to the signature of the low-level builtin given by
575 s390_adjust_builtin_arglist (unsigned int ob_fcode
, tree decl
,
576 vec
<tree
, va_gc
> **arglist
)
579 int src_arg_index
, dest_arg_index
;
580 vec
<tree
, va_gc
> *folded_args
= NULL
;
582 /* We at most add one more operand to the list. */
583 vec_alloc (folded_args
, (*arglist
)->allocated () + 1);
584 for (arg_chain
= TYPE_ARG_TYPES (TREE_TYPE (decl
)),
585 src_arg_index
= 0, dest_arg_index
= 0;
586 !VOID_TYPE_P (TREE_VALUE (arg_chain
));
587 arg_chain
= TREE_CHAIN (arg_chain
), dest_arg_index
++)
589 bool arg_assigned_p
= false;
592 /* For all these the low level builtin needs an additional flags parameter. */
593 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx
:
594 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx
:
595 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx
:
596 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx
:
597 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq
:
598 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne
:
599 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc
:
600 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc
:
601 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc
:
602 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc
:
603 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc
:
604 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc
:
605 if (dest_arg_index
== 2)
607 folded_args
->quick_push (build_int_cst (integer_type_node
,
608 s390_get_vstring_flags (ob_fcode
)));
609 arg_assigned_p
= true;
612 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx
:
613 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx
:
614 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx
:
615 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx
:
616 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg
:
617 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg
:
618 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc
:
619 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc
:
620 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc
:
621 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc
:
622 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc
:
623 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc
:
624 if (dest_arg_index
== 3)
626 folded_args
->quick_push (build_int_cst (integer_type_node
,
627 s390_get_vstring_flags (ob_fcode
)));
628 arg_assigned_p
= true;
631 case S390_OVERLOADED_BUILTIN_s390_vec_sel
:
632 case S390_OVERLOADED_BUILTIN_s390_vec_insert
:
633 case S390_OVERLOADED_BUILTIN_s390_vec_load_len
:
634 /* Swap the first to arguments. It is better to do it here
635 instead of the header file to avoid operand checking
636 throwing error messages for a weird operand index. */
637 if (dest_arg_index
< 2)
639 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
640 (**arglist
)[1 - dest_arg_index
]));
642 arg_assigned_p
= true;
645 case S390_OVERLOADED_BUILTIN_s390_vec_store_len
:
646 if (dest_arg_index
== 1 || dest_arg_index
== 2)
648 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
649 (**arglist
)[3 - dest_arg_index
]));
651 arg_assigned_p
= true;
655 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry
:
659 if (dest_arg_index
== 1)
661 switch (tree_to_uhwi ((**arglist
)[src_arg_index
]))
663 case 64: code
= 0; break;
664 case 128: code
= 1; break;
665 case 256: code
= 2; break;
666 case 512: code
= 3; break;
667 case 1024: code
= 4; break;
668 case 2048: code
= 5; break;
669 case 4096: code
= 6; break;
671 error ("valid values for builtin %qF argument %d are 64, "
672 "128, 256, 512, 1024, 2048, and 4096", decl
,
676 folded_args
->quick_push (build_int_cst (integer_type_node
,
679 arg_assigned_p
= true;
683 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask
:
684 /* Duplicate the first src arg. */
685 if (dest_arg_index
== 0)
687 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
688 (**arglist
)[src_arg_index
]));
689 arg_assigned_p
= true;
697 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
698 (**arglist
)[src_arg_index
]));
702 *arglist
= folded_args
;
705 /* Check whether the arguments in ARGLIST match the function type
706 DEF_TYPE. Return the number of argument types which required
707 conversion/promotion in order to make it match.
708 0 stands for a perfect match - all operand types match without changes
709 INT_MAX stands for a mismatch. */
711 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex
,
712 vec
<tree
, va_gc
> *arglist
)
717 for (i
= 0; i
< vec_safe_length (arglist
); i
++)
719 tree b_arg_type
= s390_builtin_types
[s390_builtin_ov_types
[typeindex
][i
+ 1]];
720 tree in_arg
= (*arglist
)[i
];
721 tree in_type
= TREE_TYPE (in_arg
);
723 if (TREE_CODE (b_arg_type
) == VECTOR_TYPE
)
725 /* Vector types have to match precisely. */
726 if (b_arg_type
!= in_type
727 && TYPE_MAIN_VARIANT (b_arg_type
) != TYPE_MAIN_VARIANT (in_type
))
731 if (lang_hooks
.types_compatible_p (in_type
, b_arg_type
))
734 if (lang_hooks
.types_compatible_p (
735 lang_hooks
.types
.type_promotes_to (in_type
),
736 lang_hooks
.types
.type_promotes_to (b_arg_type
)))
742 /* In this stage the C++ frontend would go ahead trying to find
743 implicit conversion chains for the argument to match the
744 target type. We will mimic this here only for our limited
745 subset of argument types. */
746 if (TREE_CODE (b_arg_type
) == INTEGER_TYPE
747 && TREE_CODE (in_type
) == INTEGER_TYPE
)
753 /* If the incoming pointer argument has more qualifiers than the
754 argument type it can still be an imperfect match. */
755 if (POINTER_TYPE_P (b_arg_type
) && POINTER_TYPE_P (in_type
)
756 && !(TYPE_QUALS (TREE_TYPE (in_type
))
757 & ~TYPE_QUALS (TREE_TYPE (b_arg_type
)))
758 && (TYPE_QUALS (TREE_TYPE (b_arg_type
))
759 & ~TYPE_QUALS (TREE_TYPE (in_type
))))
762 build_qualified_type (TREE_TYPE (in_type
),
763 TYPE_QUALS (TREE_TYPE (b_arg_type
)));
765 if (lang_hooks
.types_compatible_p (qual_in_type
,
766 TREE_TYPE (b_arg_type
)))
774 if (TARGET_DEBUG_ARG
)
775 fprintf (stderr
, " mismatch in operand: %d\n", i
+ 1);
782 /* Return the number of elements in the vector arguments of FNDECL in
783 case all it matches for all vector arguments, -1 otherwise. */
785 s390_vec_n_elem (tree fndecl
)
790 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) == VECTOR_TYPE
)
791 n_elem
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl
))));
793 for (b_arg_chain
= TYPE_ARG_TYPES (TREE_TYPE (fndecl
));
794 !VOID_TYPE_P (TREE_VALUE (b_arg_chain
));
795 b_arg_chain
= TREE_CHAIN (b_arg_chain
))
798 if (TREE_CODE (TREE_VALUE (b_arg_chain
)) != VECTOR_TYPE
)
800 tmp_n_elem
= TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain
));
801 if (n_elem
!= -1 && n_elem
!= tmp_n_elem
)
809 /* Return a tree expression for a call to the overloaded builtin
810 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
812 s390_resolve_overloaded_builtin (location_t loc
,
814 void *passed_arglist
)
816 vec
<tree
, va_gc
> *arglist
= static_cast<vec
<tree
, va_gc
> *> (passed_arglist
);
817 unsigned int in_args_num
= vec_safe_length (arglist
);
818 unsigned int ob_args_num
= 0;
819 unsigned int ob_fcode
= DECL_FUNCTION_CODE (ob_fndecl
);
820 enum s390_overloaded_builtin_vars bindex
;
822 int last_match_type
= INT_MAX
;
823 int last_match_index
= -1;
824 unsigned int all_op_flags
;
826 tree target_builtin_decl
, b_arg_chain
, return_type
;
827 enum s390_builtin_ov_type_index last_match_fntype_index
;
829 if (TARGET_DEBUG_ARG
)
831 "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
832 (int)ob_fcode
, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl
)),
833 ob_fcode
< S390_BUILTIN_MAX
? "not" : "");
835 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
836 if (ob_fcode
< S390_BUILTIN_MAX
)
838 if (bflags_for_builtin(ob_fcode
) & B_INT
)
841 "Builtin %qF is for GCC internal use only.",
843 return error_mark_node
;
848 ob_fcode
-= S390_BUILTIN_MAX
;
850 for (b_arg_chain
= TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl
));
851 !VOID_TYPE_P (TREE_VALUE (b_arg_chain
));
852 b_arg_chain
= TREE_CHAIN (b_arg_chain
))
855 if (ob_args_num
!= in_args_num
)
858 "Mismatch in number of arguments for builtin %qF. "
859 "Expected: %d got %d", ob_fndecl
,
860 ob_args_num
, in_args_num
);
861 return error_mark_node
;
864 for (i
= 0; i
< in_args_num
; i
++)
865 if ((*arglist
)[i
] == error_mark_node
)
866 return error_mark_node
;
868 /* Overloaded builtins without any variants are directly expanded here. */
869 if (desc_start_for_overloaded_builtin
[ob_fcode
] ==
870 S390_OVERLOADED_BUILTIN_VAR_MAX
)
871 return s390_expand_overloaded_builtin (loc
, ob_fcode
, arglist
, NULL_TREE
);
873 for (bindex
= desc_start_for_overloaded_builtin
[ob_fcode
];
874 bindex
<= desc_end_for_overloaded_builtin
[ob_fcode
];
875 bindex
= (enum s390_overloaded_builtin_vars
)((int)bindex
+ 1))
878 enum s390_builtin_ov_type_index type_index
=
879 type_for_overloaded_builtin_var
[bindex
];
881 if (TARGET_DEBUG_ARG
)
882 fprintf (stderr
, "checking variant number: %d", (int)bindex
);
884 match_type
= s390_fn_types_compatible (type_index
, arglist
);
886 if (match_type
== INT_MAX
)
889 if (TARGET_DEBUG_ARG
)
891 " %s match score: %d\n", match_type
== 0 ? "perfect" : "imperfect",
894 if (match_type
< last_match_type
)
897 last_match_type
= match_type
;
898 last_match_fntype_index
= type_index
;
899 last_match_index
= bindex
;
901 else if (match_type
== last_match_type
)
905 if (last_match_type
== INT_MAX
)
907 error_at (loc
, "invalid parameter combination for intrinsic %qs",
908 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl
)));
909 return error_mark_node
;
911 else if (num_matches
> 1)
913 error_at (loc
, "ambiguous overload for intrinsic %qs",
914 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl
)));
915 return error_mark_node
;
918 if (bt_for_overloaded_builtin_var
[last_match_index
] == S390_BUILTIN_MAX
)
919 target_builtin_decl
= ob_fndecl
;
921 target_builtin_decl
= s390_builtin_decls
[bt_for_overloaded_builtin_var
[last_match_index
]];
923 all_op_flags
= opflags_overloaded_builtin_var
[last_match_index
];
924 return_type
= s390_builtin_types
[s390_builtin_ov_types
[last_match_fntype_index
][0]];
926 /* Check for the operand flags in the overloaded builtin variant. */
927 for (i
= 0; i
< ob_args_num
; i
++)
929 unsigned int op_flags
= all_op_flags
& ((1 << O_SHIFT
) - 1);
930 tree arg
= (*arglist
)[i
];
931 tree type
= s390_builtin_types
[s390_builtin_ov_types
[last_match_fntype_index
][i
+ 1]];
933 all_op_flags
= all_op_flags
>> O_SHIFT
;
935 if (op_flags
== O_ELEM
)
937 int n_elem
= s390_vec_n_elem (target_builtin_decl
);
938 gcc_assert (n_elem
> 0);
939 gcc_assert (type
== integer_type_node
);
940 (*arglist
)[i
] = build2 (BIT_AND_EXPR
, integer_type_node
,
941 fold_convert (integer_type_node
, arg
),
942 build_int_cst (NULL_TREE
, n_elem
- 1));
945 if (TREE_CODE (arg
) != INTEGER_CST
|| !O_IMM_P (op_flags
))
948 if ((TYPE_UNSIGNED (type
)
949 && !int_fits_type_p (arg
, c_common_unsigned_type (type
)))
950 || (!TYPE_UNSIGNED (type
)
951 && !int_fits_type_p (arg
, c_common_signed_type (type
))))
953 error("constant argument %d for builtin %qF is out "
954 "of range for target type",
955 i
+ 1, target_builtin_decl
);
956 return error_mark_node
;
959 if (TREE_CODE (arg
) == INTEGER_CST
960 && !s390_const_operand_ok (arg
, i
+ 1, op_flags
, target_builtin_decl
))
961 return error_mark_node
;
964 /* Handle builtins we expand directly - without mapping it to a low
966 if (bt_for_overloaded_builtin_var
[last_match_index
] == S390_BUILTIN_MAX
)
967 return s390_expand_overloaded_builtin (loc
, ob_fcode
, arglist
, return_type
);
969 s390_adjust_builtin_arglist (ob_fcode
, target_builtin_decl
, &arglist
);
971 if (VOID_TYPE_P (return_type
))
972 return build_function_call_vec (loc
, vNULL
, target_builtin_decl
,
975 return fully_fold_convert (return_type
,
976 build_function_call_vec (loc
, vNULL
, target_builtin_decl
,
980 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
982 s390_register_target_pragmas (void)
984 targetm
.resolve_overloaded_builtin
= s390_resolve_overloaded_builtin
;
985 #if S390_USE_TARGET_ATTRIBUTE
986 /* Update pragma hook to allow parsing #pragma GCC target. */
987 targetm
.target_option
.pragma_parse
= s390_pragma_target_parse
;