S/390: Rename __S390_ARCH_LEVEL__ to __ARCH__.
[official-gcc.git] / gcc / config / s390 / s390-c.c
blob8f184eaa9131996a2353d11b13d39dc517833476
1 /* Language specific subroutines used for code generation on IBM S/390
2 and zSeries
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)
12 any later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>.
23 Based on gcc/config/rs6000/rs6000-c.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. */
30 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "target.h"
34 #include "tree.h"
35 #include "c-family/c-common.h"
36 #include "c/c-tree.h"
37 #include "memmodel.h"
38 #include "tm_p.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
55 s390-builtins.def. */
56 static enum s390_builtin_ov_type_index
57 type_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX + 1] =
59 #undef B_DEF
60 #undef OB_DEF
61 #undef OB_DEF_VAR
62 #define B_DEF(...)
63 #define OB_DEF(...)
64 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, FNTYPE) FNTYPE,
65 #include "s390-builtins.def"
66 BT_OV_MAX
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] =
76 #undef B_DEF
77 #undef OB_DEF
78 #undef OB_DEF_VAR
79 #define B_DEF(...)
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] =
93 #undef B_DEF
94 #undef OB_DEF
95 #undef OB_DEF_VAR
96 #define B_DEF(...)
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] =
107 #undef DEF_TYPE
108 #undef DEF_POINTER_TYPE
109 #undef DEF_DISTINCT_TYPE
110 #undef DEF_VECTOR_TYPE
111 #undef DEF_OPAQUE_VECTOR_TYPE
112 #undef DEF_FN_TYPE
113 #undef DEF_OV_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] = {
126 #undef B_DEF
127 #undef OB_DEF
128 #undef OB_DEF_VAR
129 #define B_DEF(...)
130 #define OB_DEF(...)
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). */
139 tree
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);
148 return result;
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);
168 return ident;
171 return 0;
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;
183 cpp_hashnode *ident;
184 static bool expand_bool_p = false;
185 int idx = 0;
186 enum rid rid_code;
188 /* The vector keyword is only expanded if the machine actually
189 provides hardware support. */
190 if (!TARGET_ZVECTOR)
191 return NULL;
193 ident = s390_categorize_keyword (tok);
195 /* Triggered when we picked a different variant in
196 s390_categorize_keyword. */
197 if (ident != expand_this)
198 expand_this = NULL;
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;
205 return ident;
208 if (ident != C_CPP_HASHNODE (__vector_keyword))
209 return expand_this;
212 tok = cpp_peek_token (pfile, idx++);
213 while (tok->type == CPP_PADDING);
214 ident = s390_categorize_keyword (tok);
216 if (!ident)
217 return expand_this;
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))
230 return expand_this;
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);
240 while (--idx > 0);
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);
251 else if (ident)
252 rid_code = (enum rid)(ident->rid_code);
255 /* vector keyword followed by type identifier: vector unsigned,
256 vector long, ...
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
266 well. */
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;
275 else
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;
288 return expand_this;
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. */
294 static void
295 s390_def_or_undef_macro (cpp_reader *pfile,
296 unsigned int mask,
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)
301 bool was_set;
302 bool set;
304 was_set = (!old_opts) ? false : old_opts->x_target_flags & mask;
305 set = new_opts->x_target_flags & mask;
306 if (was_set == set)
307 return;
308 if (set)
309 cpp_define (pfile, macro_def);
310 else
311 cpp_undef (pfile, macro_undef);
314 /* Internal function to either define or undef the appropriate system
315 macros. */
316 static void
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)))",
329 "__vector__");
330 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
331 "__bool=__attribute__((s390_vector_bool)) unsigned",
332 "__bool");
334 char macro_def[64];
335 int arch_level;
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. */
340 arch_level--;
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);
348 if (!flag_iso)
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. */
381 void
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__");
389 if (TARGET_ZARCH)
390 cpp_define (pfile, "__zarch__");
391 if (TARGET_64BIT)
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. */
404 static bool
405 s390_pragma_target_parse (tree args, tree pop_target)
407 tree prev_tree = build_target_option_node (&global_options);
408 tree cur_tree;
410 if (! args)
411 cur_tree = pop_target;
412 else
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));
420 return false;
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;
449 return true;
451 #endif
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 */
458 static tree
459 s390_expand_overloaded_builtin (location_t loc,
460 unsigned fcode,
461 vec<tree, va_gc> *arglist,
462 tree return_type)
464 switch (fcode)
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])),
484 (*arglist)[0]);
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]);
489 default:
490 gcc_unreachable ();
494 /* invert result */
495 #define __VSTRING_FLAG_IN 8
496 /* result type */
497 #define __VSTRING_FLAG_RT 4
498 /* zero search */
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. */
505 static unsigned int
506 s390_get_vstring_flags (int ob_fcode)
508 unsigned int flags = 0;
510 switch (ob_fcode)
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;
525 break;
526 default:
527 break;
529 switch (ob_fcode)
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;
541 break;
542 default:
543 break;
545 switch (ob_fcode)
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;
557 break;
558 default:
559 break;
561 switch (ob_fcode)
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;
576 break;
577 default:
578 break;
580 return flags;
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
591 DECL. */
592 static void
593 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
594 vec<tree, va_gc> **arglist)
596 tree arg_chain;
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;
608 switch (ob_fcode)
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;
629 break;
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;
648 break;
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]));
659 src_arg_index++;
660 arg_assigned_p = true;
662 break;
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]));
668 src_arg_index++;
669 arg_assigned_p = true;
671 break;
673 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
675 int code;
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;
688 default:
689 error ("valid values for builtin %qF argument %d are 64, "
690 "128, 256, 512, 1024, 2048, and 4096", decl,
691 src_arg_index + 1);
692 return;
694 folded_args->quick_push (build_int_cst (integer_type_node,
695 code));
696 src_arg_index++;
697 arg_assigned_p = true;
700 break;
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;
709 break;
710 default:
711 break;
713 if (!arg_assigned_p)
715 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
716 (**arglist)[src_arg_index]));
717 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. */
728 static int
729 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
730 vec<tree, va_gc> *arglist)
732 unsigned int i;
733 int match_type = 0;
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))
746 goto mismatch;
749 if (lang_hooks.types_compatible_p (in_type, b_arg_type))
750 continue;
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)))
756 match_type++;
757 continue;
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)
767 match_type++;
768 continue;
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))))
779 tree qual_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)))
786 match_type++;
787 continue;
791 mismatch:
792 if (TARGET_DEBUG_ARG)
793 fprintf (stderr, " mismatch in operand: %d\n", i + 1);
794 return INT_MAX;
797 return match_type;
800 /* Return the number of elements in the vector arguments of FNDECL in
801 case all it matches for all vector arguments, -1 otherwise. */
802 static int
803 s390_vec_n_elem (tree fndecl)
805 tree b_arg_chain;
806 int n_elem = -1;
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))
815 int tmp_n_elem;
816 if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
817 continue;
818 tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
819 if (n_elem != -1 && n_elem != tmp_n_elem)
820 return -1;
821 n_elem = tmp_n_elem;
823 return n_elem;
827 /* Return a tree expression for a call to the overloaded builtin
828 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
829 tree
830 s390_resolve_overloaded_builtin (location_t loc,
831 tree ob_fndecl,
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;
839 unsigned int i;
840 int last_match_type = INT_MAX;
841 int last_match_index = -1;
842 unsigned int all_op_flags;
843 int num_matches = 0;
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)
848 fprintf (stderr,
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)
858 error_at (loc,
859 "builtin %qF is for GCC internal use only.",
860 ob_fndecl);
861 return error_mark_node;
863 return NULL_TREE;
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))
871 ob_args_num++;
873 if (ob_args_num != in_args_num)
875 error_at (loc,
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))
895 int match_type;
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)
905 continue;
907 if (TARGET_DEBUG_ARG)
908 fprintf (stderr,
909 " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
910 match_type);
912 if (match_type < last_match_type)
914 num_matches = 1;
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)
920 num_matches++;
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;
938 else
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))
964 continue;
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
983 level builtin. */
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,
991 arglist, NULL);
992 else
993 return fully_fold_convert (return_type,
994 build_function_call_vec (loc, vNULL, target_builtin_decl,
995 arglist, NULL));
998 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
999 void
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;
1006 #endif