1 /* Language specific subroutines used for code generation on IBM S/390
3 Copyright (C) 2015 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 /* Define platform dependent macros. */
292 s390_cpu_cpp_builtins (cpp_reader *pfile)
294 cpp_assert (pfile, "cpu=s390");
295 cpp_assert (pfile, "machine=s390");
296 cpp_define (pfile, "__s390__");
298 cpp_define (pfile, "__zarch__");
300 cpp_define (pfile, "__s390x__");
301 if (TARGET_LONG_DOUBLE_128)
302 cpp_define (pfile, "__LONG_DOUBLE_128__");
304 cpp_define (pfile, "__HTM__");
307 cpp_define (pfile, "__VEC__=10301");
308 cpp_define (pfile, "__vector=__attribute__((vector_size(16)))");
309 cpp_define (pfile, "__bool=__attribute__((s390_vector_bool)) unsigned");
313 cpp_define (pfile, "__VECTOR_KEYWORD_SUPPORTED__");
314 cpp_define (pfile, "vector=vector");
315 cpp_define (pfile, "bool=bool");
317 __vector_keyword = get_identifier ("__vector");
318 C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
320 vector_keyword = get_identifier ("vector");
321 C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
323 __bool_keyword = get_identifier ("__bool");
324 C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
326 bool_keyword = get_identifier ("bool");
327 C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
329 _Bool_keyword = get_identifier ("_Bool");
330 C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
332 /* Enable context-sensitive macros. */
333 cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
338 /* Expand builtins which can directly be mapped to tree expressions.
339 LOC - location information
340 FCODE - function code of the builtin
341 ARGLIST - value supposed to be passed as arguments
342 RETURN-TYPE - expected return type of the builtin */
344 s390_expand_overloaded_builtin (location_t loc,
346 vec<tree, va_gc> *arglist,
351 case S390_OVERLOADED_BUILTIN_s390_vec_step:
352 if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
354 error_at (loc, "Builtin vec_step can only be used on vector types.");
355 return error_mark_node;
357 return build_int_cst (NULL_TREE,
358 TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
359 case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
360 case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
361 return build2 (MEM_REF, return_type,
362 fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
363 build_int_cst (TREE_TYPE ((*arglist)[1]), 0));
364 case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
365 case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
366 return build2 (MODIFY_EXPR, TREE_TYPE((*arglist)[0]),
367 build1 (INDIRECT_REF, TREE_TYPE((*arglist)[0]),
368 fold_build_pointer_plus ((*arglist)[2], (*arglist)[1])),
370 case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
371 return build_constructor_va (return_type, 2,
372 NULL_TREE, (*arglist)[0],
373 NULL_TREE, (*arglist)[1]);
380 #define __VSTRING_FLAG_IN 8
382 #define __VSTRING_FLAG_RT 4
384 #define __VSTRING_FLAG_ZS 2
385 /* set condition code */
386 #define __VSTRING_FLAG_CS 1
388 /* Return the flags value to be used for string low-level builtins
389 when expanded from overloaded builtin OB_FCODE. */
391 s390_get_vstring_flags (int ob_fcode)
393 unsigned int flags = 0;
397 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
398 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
399 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
400 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
401 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
402 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
403 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
404 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
405 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
406 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
407 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
408 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
409 flags |= __VSTRING_FLAG_IN;
417 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
418 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
419 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
420 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
421 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
422 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
423 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
424 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
425 flags |= __VSTRING_FLAG_RT;
433 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
434 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
435 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
436 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
437 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
438 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
439 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
440 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
441 flags |= __VSTRING_FLAG_ZS;
448 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
449 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
450 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
451 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
452 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
453 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
454 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
455 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
456 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
457 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
458 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
459 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
460 flags |= __VSTRING_FLAG_CS;
467 #undef __VSTRING_FLAG_IN
468 #undef __VSTRING_FLAG_RT
469 #undef __VSTRING_FLAG_ZS
470 #undef __VSTRING_FLAG_CS
472 /* For several overloaded builtins the argument lists do not match
473 exactly the signature of a low-level builtin. This function
474 adjusts the argument list ARGLIST for the overloaded builtin
475 OB_FCODE to the signature of the low-level builtin given by
478 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
479 vec<tree, va_gc> **arglist)
482 int src_arg_index, dest_arg_index;
483 vec<tree, va_gc> *folded_args = NULL;
485 /* We at most add one more operand to the list. */
486 vec_alloc (folded_args, (*arglist)->allocated () + 1);
487 for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
488 src_arg_index = 0, dest_arg_index = 0;
489 !VOID_TYPE_P (TREE_VALUE (arg_chain));
490 arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
492 bool arg_assigned_p = false;
495 /* For all these the low level builtin needs an additional flags parameter. */
496 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
497 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
498 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
499 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
500 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
501 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
502 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
503 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
504 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
505 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
506 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
507 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
508 if (dest_arg_index == 2)
510 folded_args->quick_push (build_int_cst (integer_type_node,
511 s390_get_vstring_flags (ob_fcode)));
512 arg_assigned_p = true;
515 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
516 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
517 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
518 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
519 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
520 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
521 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
522 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
523 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
524 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
525 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
526 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
527 if (dest_arg_index == 3)
529 folded_args->quick_push (build_int_cst (integer_type_node,
530 s390_get_vstring_flags (ob_fcode)));
531 arg_assigned_p = true;
534 case S390_OVERLOADED_BUILTIN_s390_vec_sel:
535 case S390_OVERLOADED_BUILTIN_s390_vec_insert:
536 case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
537 /* Swap the first to arguments. It is better to do it here
538 instead of the header file to avoid operand checking
539 throwing error messages for a weird operand index. */
540 if (dest_arg_index < 2)
542 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
543 (**arglist)[1 - dest_arg_index]));
545 arg_assigned_p = true;
548 case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
549 if (dest_arg_index == 1 || dest_arg_index == 2)
551 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
552 (**arglist)[3 - dest_arg_index]));
554 arg_assigned_p = true;
558 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
562 if (dest_arg_index == 1)
564 switch (tree_to_uhwi ((**arglist)[src_arg_index]))
566 case 64: code = 0; break;
567 case 128: code = 1; break;
568 case 256: code = 2; break;
569 case 512: code = 3; break;
570 case 1024: code = 4; break;
571 case 2048: code = 5; break;
572 case 4096: code = 6; break;
574 error ("valid values for builtin %qF argument %d are 64, "
575 "128, 256, 512, 1024, 2048, and 4096", decl,
579 folded_args->quick_push (build_int_cst (integer_type_node,
582 arg_assigned_p = true;
586 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
587 /* Duplicate the first src arg. */
588 if (dest_arg_index == 0)
590 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
591 (**arglist)[src_arg_index]));
592 arg_assigned_p = true;
600 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
601 (**arglist)[src_arg_index]));
605 *arglist = folded_args;
608 /* Check whether the arguments in ARGLIST match the function type
609 DEF_TYPE. Return the number of argument types which required
610 conversion/promotion in order to make it match.
611 0 stands for a perfect match - all operand types match without changes
612 INT_MAX stands for a mismatch. */
614 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
615 vec<tree, va_gc> *arglist)
620 for (i = 0; i < vec_safe_length (arglist); i++)
622 tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
623 tree in_arg = (*arglist)[i];
624 tree in_type = TREE_TYPE (in_arg);
626 if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
628 /* Vector types have to match precisely. */
629 if (b_arg_type != in_type
630 && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
634 if (lang_hooks.types_compatible_p (in_type, b_arg_type))
637 if (lang_hooks.types_compatible_p (
638 lang_hooks.types.type_promotes_to (in_type),
639 lang_hooks.types.type_promotes_to (b_arg_type)))
645 /* In this stage the C++ frontend would go ahead trying to find
646 implicit conversion chains for the argument to match the
647 target type. We will mimic this here only for our limited
648 subset of argument types. */
649 if (TREE_CODE (b_arg_type) == INTEGER_TYPE
650 && TREE_CODE (in_type) == INTEGER_TYPE)
656 /* If the incoming pointer argument has more qualifiers than the
657 argument type it can still be an imperfect match. */
658 if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
659 && !(TYPE_QUALS (TREE_TYPE (in_type))
660 & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
661 && (TYPE_QUALS (TREE_TYPE (b_arg_type))
662 & ~TYPE_QUALS (TREE_TYPE (in_type))))
665 build_qualified_type (TREE_TYPE (in_type),
666 TYPE_QUALS (TREE_TYPE (b_arg_type)));
668 if (lang_hooks.types_compatible_p (qual_in_type,
669 TREE_TYPE (b_arg_type)))
677 if (TARGET_DEBUG_ARG)
678 fprintf (stderr, " mismatch in operand: %d\n", i + 1);
685 /* Return the number of elements in the vector arguments of FNDECL in
686 case all it matches for all vector arguments, -1 otherwise. */
688 s390_vec_n_elem (tree fndecl)
693 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) == VECTOR_TYPE)
694 n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
696 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
697 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
698 b_arg_chain = TREE_CHAIN (b_arg_chain))
701 if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
703 tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
704 if (n_elem != -1 && n_elem != tmp_n_elem)
712 /* Return a tree expression for a call to the overloaded builtin
713 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
715 s390_resolve_overloaded_builtin (location_t loc,
717 void *passed_arglist)
719 vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
720 unsigned int in_args_num = vec_safe_length (arglist);
721 unsigned int ob_args_num = 0;
722 unsigned int ob_fcode = DECL_FUNCTION_CODE (ob_fndecl);
723 enum s390_overloaded_builtin_vars bindex;
725 int last_match_type = INT_MAX;
726 int last_match_index = -1;
727 unsigned int all_op_flags;
729 tree target_builtin_decl, b_arg_chain, return_type;
730 enum s390_builtin_ov_type_index last_match_fntype_index;
732 if (TARGET_DEBUG_ARG)
734 "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
735 (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
736 ob_fcode < S390_BUILTIN_MAX ? "not" : "");
738 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
739 if (ob_fcode < S390_BUILTIN_MAX)
741 if (bflags_for_builtin(ob_fcode) & B_INT)
744 "Builtin %qF is for GCC internal use only.",
746 return error_mark_node;
751 ob_fcode -= S390_BUILTIN_MAX;
753 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
754 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
755 b_arg_chain = TREE_CHAIN (b_arg_chain))
758 if (ob_args_num != in_args_num)
761 "Mismatch in number of arguments for builtin %qF. "
762 "Expected: %d got %d", ob_fndecl,
763 ob_args_num, in_args_num);
764 return error_mark_node;
767 for (i = 0; i < in_args_num; i++)
768 if ((*arglist)[i] == error_mark_node)
769 return error_mark_node;
771 /* Overloaded builtins without any variants are directly expanded here. */
772 if (desc_start_for_overloaded_builtin[ob_fcode] ==
773 S390_OVERLOADED_BUILTIN_VAR_MAX)
774 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
776 for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
777 bindex <= desc_end_for_overloaded_builtin[ob_fcode];
778 bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
781 enum s390_builtin_ov_type_index type_index =
782 type_for_overloaded_builtin_var[bindex];
784 if (TARGET_DEBUG_ARG)
785 fprintf (stderr, "checking variant number: %d", (int)bindex);
787 match_type = s390_fn_types_compatible (type_index, arglist);
789 if (match_type == INT_MAX)
792 if (TARGET_DEBUG_ARG)
794 " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
797 if (match_type < last_match_type)
800 last_match_type = match_type;
801 last_match_fntype_index = type_index;
802 last_match_index = bindex;
804 else if (match_type == last_match_type)
808 if (last_match_type == INT_MAX)
810 error_at (loc, "invalid parameter combination for intrinsic");
811 return error_mark_node;
813 else if (num_matches > 1)
815 error_at (loc, "ambiguous overload for intrinsic: %s\n",
816 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
817 return error_mark_node;
820 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
821 target_builtin_decl = ob_fndecl;
823 target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
825 all_op_flags = opflags_overloaded_builtin_var[last_match_index];
826 return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
828 /* Check for the operand flags in the overloaded builtin variant. */
829 for (i = 0; i < ob_args_num; i++)
831 unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
832 tree arg = (*arglist)[i];
833 tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
835 all_op_flags = all_op_flags >> O_SHIFT;
837 if (op_flags == O_ELEM)
839 int n_elem = s390_vec_n_elem (target_builtin_decl);
840 gcc_assert (n_elem > 0);
841 gcc_assert (type == integer_type_node);
842 (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
843 fold_convert (integer_type_node, arg),
844 build_int_cst (NULL_TREE, n_elem - 1));
847 if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
850 if ((TYPE_UNSIGNED (type)
851 && !int_fits_type_p (arg, c_common_unsigned_type (type)))
852 || (!TYPE_UNSIGNED (type)
853 && !int_fits_type_p (arg, c_common_signed_type (type))))
855 error("constant argument %d for builtin %qF is out "
856 "of range for target type",
857 i + 1, target_builtin_decl);
858 return error_mark_node;
861 if (TREE_CODE (arg) == INTEGER_CST
862 && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
863 return error_mark_node;
866 /* Handle builtins we expand directly - without mapping it to a low
868 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
869 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
871 s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
873 if (VOID_TYPE_P (return_type))
874 return build_function_call_vec (loc, vNULL, target_builtin_decl,
877 return fully_fold_convert (return_type,
878 build_function_call_vec (loc, vNULL, target_builtin_decl,
882 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
884 s390_register_target_pragmas (void)
886 targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;