Home | History | Annotate | Line # | Download | only in s390
s390-c.cc revision 1.1
      1 /* Language specific subroutines used for code generation on IBM S/390
      2    and zSeries
      3    Copyright (C) 2015-2022 Free Software Foundation, Inc.
      4 
      5    Contributed by Andreas Krebbel (Andreas.Krebbel (at) de.ibm.com).
      6 
      7    This file is part of GCC.
      8 
      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.
     13 
     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.
     18 
     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/>.
     22 
     23    Based on gcc/config/rs6000/rs6000-c.cc.
     24 
     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.  */
     29 
     30 #define IN_TARGET_CODE 1
     31 
     32 #include "config.h"
     33 #include "system.h"
     34 #include "coretypes.h"
     35 #include "target.h"
     36 #include "tree.h"
     37 #include "c-family/c-common.h"
     38 #include "c/c-tree.h"
     39 #include "memmodel.h"
     40 #include "tm_p.h"
     41 #include "stringpool.h"
     42 #include "c-family/c-pragma.h"
     43 #include "langhooks.h"
     44 #include "tree-pretty-print.h"
     45 
     46 #include "s390-builtins.h"
     47 
     48 static GTY(()) tree __vector_keyword;
     49 static GTY(()) tree vector_keyword;
     50 static GTY(()) tree __bool_keyword;
     51 static GTY(()) tree bool_keyword;
     52 static GTY(()) tree _Bool_keyword;
     53 
     54 
     55 /* Generate an array holding all the descriptions of variants of
     56    overloaded builtins defined with OB_DEF_VAR in
     57    s390-builtins.def.  */
     58 static enum s390_builtin_ov_type_index
     59 type_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX + 1] =
     60   {
     61 #undef B_DEF
     62 #undef OB_DEF
     63 #undef OB_DEF_VAR
     64 #define B_DEF(...)
     65 #define OB_DEF(...)
     66 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, OPFLAGS, FNTYPE) FNTYPE,
     67 #include "s390-builtins.def"
     68     BT_OV_MAX
     69   };
     70 
     71 
     72 /* Generate an array indexed by an overloaded builtin index returning
     73    the first index in desc_for_overloaded_builtin_var where the
     74    variants for the builtin can be found.  */
     75 static enum s390_overloaded_builtin_vars
     76 desc_start_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
     77   {
     78 #undef B_DEF
     79 #undef OB_DEF
     80 #undef OB_DEF_VAR
     81 #define B_DEF(...)
     82 #define OB_DEF(NAME, FIRST_VAR_NAME,...)	\
     83     S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
     84 #define OB_DEF_VAR(...)
     85     #include "s390-builtins.def"
     86     S390_OVERLOADED_BUILTIN_VAR_MAX
     87   };
     88 
     89 /* Generate an array indexed by an overloaded builtin index returning
     90    the last index in desc_for_overloaded_builtin_var where the
     91    variants for the builtin can be found.  */
     92 static enum s390_overloaded_builtin_vars
     93 desc_end_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
     94   {
     95 #undef B_DEF
     96 #undef OB_DEF
     97 #undef OB_DEF_VAR
     98 #define B_DEF(...)
     99 #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...)	\
    100     S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
    101 #define OB_DEF_VAR(...)
    102     #include "s390-builtins.def"
    103     S390_OVERLOADED_BUILTIN_VAR_MAX
    104   };
    105 
    106 static enum s390_builtin_type_index
    107 s390_builtin_ov_types[BT_OV_MAX][MAX_OV_OPERANDS] =
    108   {
    109 #undef DEF_TYPE
    110 #undef DEF_POINTER_TYPE
    111 #undef DEF_DISTINCT_TYPE
    112 #undef DEF_VECTOR_TYPE
    113 #undef DEF_OPAQUE_VECTOR_TYPE
    114 #undef DEF_FN_TYPE
    115 #undef DEF_OV_TYPE
    116 #define DEF_TYPE(...)
    117 #define DEF_POINTER_TYPE(...)
    118 #define DEF_DISTINCT_TYPE(...)
    119 #define DEF_VECTOR_TYPE(...)
    120 #define DEF_OPAQUE_VECTOR_TYPE(...)
    121 #define DEF_FN_TYPE(...)
    122 #define DEF_OV_TYPE(INDEX, args...) { args },
    123 #include "s390-builtin-types.def"
    124   };
    125 
    126 static const enum s390_builtins
    127 bt_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX] = {
    128 #undef B_DEF
    129 #undef OB_DEF
    130 #undef OB_DEF_VAR
    131 #define B_DEF(...)
    132 #define OB_DEF(...)
    133 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
    134 
    135 #include "s390-builtins.def"
    136   };
    137 
    138 /* In addition to calling fold_convert for EXPR of type TYPE, also
    139    call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
    140    hiding there (PR47197).  */
    141 tree
    142 fully_fold_convert (tree type, tree expr)
    143 {
    144   tree result = fold_convert (type, expr);
    145   bool maybe_const = true;
    146 
    147   if (!c_dialect_cxx ())
    148     result = c_fully_fold (result, false, &maybe_const);
    149 
    150   return result;
    151 }
    152 
    153 /* Unify the different variants to the same nodes in order to keep the
    154    code working with it simple.  */
    155 static cpp_hashnode *
    156 s390_categorize_keyword (const cpp_token *tok)
    157 {
    158   if (tok->type == CPP_NAME)
    159     {
    160       cpp_hashnode *ident = tok->val.node.node;
    161 
    162       if (ident == C_CPP_HASHNODE (vector_keyword))
    163 	return C_CPP_HASHNODE (__vector_keyword);
    164 
    165       if (ident == C_CPP_HASHNODE (bool_keyword))
    166 	return C_CPP_HASHNODE (__bool_keyword);
    167 
    168       if (ident == C_CPP_HASHNODE (_Bool_keyword))
    169 	return C_CPP_HASHNODE (__bool_keyword);
    170       return ident;
    171     }
    172 
    173   return 0;
    174 }
    175 
    176 
    177 /* Called to decide whether a conditional macro should be expanded.
    178    Since we have exactly one such macro (i.e, 'vector'), we do not
    179    need to examine the 'tok' parameter.  */
    180 
    181 static cpp_hashnode *
    182 s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
    183 {
    184   cpp_hashnode *expand_this = tok->val.node.node;
    185   cpp_hashnode *ident;
    186   static bool expand_bool_p = false;
    187   int idx = 0;
    188   enum rid rid_code;
    189 
    190   /* The vector keyword is only expanded if the machine actually
    191      provides hardware support.  */
    192   if (!TARGET_ZVECTOR)
    193     return NULL;
    194 
    195   ident = s390_categorize_keyword (tok);
    196 
    197   /* Triggered when we picked a different variant in
    198      s390_categorize_keyword.  */
    199   if (ident != expand_this)
    200     expand_this = NULL;
    201 
    202   /* The vector keyword has been found already and we remembered to
    203      expand the next bool.  */
    204   if (expand_bool_p && ident == C_CPP_HASHNODE (__bool_keyword))
    205     {
    206       expand_bool_p = false;
    207       return ident;
    208     }
    209 
    210   if (ident != C_CPP_HASHNODE (__vector_keyword))
    211     return expand_this;
    212 
    213   do
    214     tok = cpp_peek_token (pfile, idx++);
    215   while (tok->type == CPP_PADDING);
    216   ident = s390_categorize_keyword (tok);
    217 
    218   if (!ident)
    219     return expand_this;
    220 
    221   /* vector bool - remember to expand the next bool. */
    222   if (ident == C_CPP_HASHNODE (__bool_keyword))
    223     {
    224       expand_bool_p = true;
    225       return C_CPP_HASHNODE (__vector_keyword);
    226     }
    227 
    228   /* The boost libraries have code with Iterator::vector vector in it.
    229      If we allow the normal handling, this module will be called
    230      recursively, and the vector will be skipped.; */
    231   if (ident == C_CPP_HASHNODE (__vector_keyword))
    232     return expand_this;
    233 
    234   rid_code = (enum rid)(ident->rid_code);
    235 
    236   if (cpp_macro_p (ident))
    237     {
    238       /* Now actually fetch the tokens we "peeked" before and do a
    239 	 lookahead for the next.  */
    240       do
    241 	(void) cpp_get_token (pfile);
    242       while (--idx > 0);
    243       do
    244 	tok = cpp_peek_token (pfile, idx++);
    245       while (tok->type == CPP_PADDING);
    246       ident = s390_categorize_keyword (tok);
    247 
    248       if (ident == C_CPP_HASHNODE (__bool_keyword))
    249 	{
    250 	  expand_bool_p = true;
    251 	  return C_CPP_HASHNODE (__vector_keyword);
    252 	}
    253       else if (ident)
    254 	rid_code = (enum rid)(ident->rid_code);
    255     }
    256 
    257   /* vector keyword followed by type identifier: vector unsigned,
    258      vector long, ...
    259      Types consisting of more than one identifier are not supported by
    260      zvector e.g. long long, long double, unsigned long int.  */
    261   if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
    262       || rid_code == RID_SHORT || rid_code == RID_SIGNED
    263       || rid_code == RID_INT || rid_code == RID_CHAR
    264       || (rid_code == RID_FLOAT && TARGET_VXE)
    265       || rid_code == RID_DOUBLE)
    266     {
    267       expand_this = C_CPP_HASHNODE (__vector_keyword);
    268       /* If the next keyword is bool, it will need to be expanded as
    269 	 well.  */
    270       do
    271 	tok = cpp_peek_token (pfile, idx++);
    272       while (tok->type == CPP_PADDING);
    273       ident = s390_categorize_keyword (tok);
    274 
    275       /* __vector long __bool a; */
    276       if (ident == C_CPP_HASHNODE (__bool_keyword))
    277 	expand_bool_p = true;
    278       else
    279 	{
    280 	  /* Triggered with: __vector long long __bool a; */
    281 	  do
    282 	    tok = cpp_peek_token (pfile, idx++);
    283 	  while (tok->type == CPP_PADDING);
    284 	  ident = s390_categorize_keyword (tok);
    285 
    286 	  if (ident == C_CPP_HASHNODE (__bool_keyword))
    287 	    expand_bool_p = true;
    288 	}
    289     }
    290 
    291   return expand_this;
    292 }
    293 
    294 /* Helper function that defines or undefines macros.  If SET is true, the macro
    295    MACRO_DEF is defined.  If SET is false, the macro MACRO_UNDEF is undefined.
    296    Nothing is done if SET and WAS_SET have the same value.  */
    297 template <typename F>
    298 static void
    299 s390_def_or_undef_macro (cpp_reader *pfile, F is_set,
    300 			 const struct cl_target_option *old_opts,
    301 			 const struct cl_target_option *new_opts,
    302 			 const char *macro_def, const char *macro_undef)
    303 {
    304   bool was_set;
    305   bool set;
    306 
    307   was_set = (!old_opts) ? false : is_set (old_opts);
    308   set = is_set (new_opts);
    309   if (was_set == set)
    310     return;
    311   if (set)
    312     cpp_define (pfile, macro_def);
    313   else
    314     cpp_undef (pfile, macro_undef);
    315 }
    316 
    317 struct target_flag_set_p
    318 {
    319   target_flag_set_p (unsigned int mask) : m_mask (mask) {}
    320 
    321   bool
    322   operator() (const struct cl_target_option *opts) const
    323   {
    324     return opts->x_target_flags & m_mask;
    325   }
    326 
    327   unsigned int m_mask;
    328 };
    329 
    330 /* Internal function to either define or undef the appropriate system
    331    macros.  */
    332 static void
    333 s390_cpu_cpp_builtins_internal (cpp_reader *pfile,
    334 				struct cl_target_option *opts,
    335 				const struct cl_target_option *old_opts)
    336 {
    337   s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_OPT_HTM), old_opts,
    338 			   opts, "__HTM__", "__HTM__");
    339   s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_OPT_VX), old_opts,
    340 			   opts, "__VX__", "__VX__");
    341   s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR), old_opts,
    342 			   opts, "__VEC__=10304", "__VEC__");
    343   s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR), old_opts,
    344 			   opts, "__vector=__attribute__((vector_size(16)))",
    345 			   "__vector__");
    346   s390_def_or_undef_macro (
    347       pfile, target_flag_set_p (MASK_ZVECTOR), old_opts, opts,
    348       "__bool=__attribute__((s390_vector_bool)) unsigned", "__bool");
    349   {
    350     char macro_def[64];
    351     gcc_assert (s390_arch != PROCESSOR_NATIVE);
    352     sprintf (macro_def, "__ARCH__=%d", processor_table[s390_arch].arch_level);
    353     cpp_undef (pfile, "__ARCH__");
    354     cpp_define (pfile, macro_def);
    355   }
    356   s390_def_or_undef_macro (
    357       pfile,
    358       [] (const struct cl_target_option *opts) { return TARGET_VXE_P (opts); },
    359       old_opts, opts, "__LONG_DOUBLE_VX__", "__LONG_DOUBLE_VX__");
    360 
    361   if (!flag_iso)
    362     {
    363       s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
    364 			       old_opts, opts, "__VECTOR_KEYWORD_SUPPORTED__",
    365 			       "__VECTOR_KEYWORD_SUPPORTED__");
    366       s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
    367 			       old_opts, opts, "vector=vector", "vector");
    368       s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
    369 			       old_opts, opts, "bool=bool", "bool");
    370       s390_def_or_undef_macro (pfile, target_flag_set_p (MASK_ZVECTOR),
    371 			       old_opts, opts, "_Bool=_Bool", "_Bool");
    372       if (TARGET_ZVECTOR_P (opts->x_target_flags) && __vector_keyword == NULL)
    373 	{
    374 	  __vector_keyword = get_identifier ("__vector");
    375 	  C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
    376 
    377 	  vector_keyword = get_identifier ("vector");
    378 	  C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
    379 
    380 	  __bool_keyword = get_identifier ("__bool");
    381 	  C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
    382 
    383 	  bool_keyword = get_identifier ("bool");
    384 	  C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
    385 
    386 	  _Bool_keyword = get_identifier ("_Bool");
    387 	  C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
    388 
    389 	  /* Enable context-sensitive macros.  */
    390 	  cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
    391 	}
    392     }
    393 }
    394 
    395 /* Define platform dependent macros.  */
    396 void
    397 s390_cpu_cpp_builtins (cpp_reader *pfile)
    398 {
    399   struct cl_target_option opts;
    400 
    401   cpp_assert (pfile, "cpu=s390");
    402   cpp_assert (pfile, "machine=s390");
    403   cpp_define (pfile, "__s390__");
    404   if (TARGET_ZARCH)
    405     cpp_define (pfile, "__zarch__");
    406   if (TARGET_64BIT)
    407     cpp_define (pfile, "__s390x__");
    408   if (TARGET_LONG_DOUBLE_128)
    409     cpp_define (pfile, "__LONG_DOUBLE_128__");
    410   cl_target_option_save (&opts, &global_options, &global_options_set);
    411   s390_cpu_cpp_builtins_internal (pfile, &opts, NULL);
    412 }
    413 
    414 #if S390_USE_TARGET_ATTRIBUTE
    415 /* Hook to validate the current #pragma GCC target and set the state, and
    416    update the macros based on what was changed.  If ARGS is NULL, then
    417    POP_TARGET is used to reset the options.  */
    418 
    419 static bool
    420 s390_pragma_target_parse (tree args, tree pop_target)
    421 {
    422   tree prev_tree = build_target_option_node (&global_options,
    423 					     &global_options_set);
    424   tree cur_tree;
    425 
    426   if (! args)
    427     cur_tree = pop_target;
    428   else
    429     {
    430       cur_tree = s390_valid_target_attribute_tree (args, &global_options,
    431 						   &global_options_set, true);
    432       if (!cur_tree || cur_tree == error_mark_node)
    433 	{
    434 	  cl_target_option_restore (&global_options, &global_options_set,
    435 				    TREE_TARGET_OPTION (prev_tree));
    436 	  return false;
    437 	}
    438     }
    439 
    440   target_option_current_node = cur_tree;
    441   s390_activate_target_options (target_option_current_node);
    442 
    443   {
    444     struct cl_target_option *prev_opt;
    445     struct cl_target_option *cur_opt;
    446 
    447     /* Figure out the previous/current differences.  */
    448     prev_opt = TREE_TARGET_OPTION (prev_tree);
    449     cur_opt = TREE_TARGET_OPTION (cur_tree);
    450 
    451     /* For the definitions, ensure all newly defined macros are considered
    452        as used for -Wunused-macros.  There is no point warning about the
    453        compiler predefined macros.  */
    454     cpp_options *cpp_opts = cpp_get_options (parse_in);
    455     unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
    456 
    457     cpp_opts->warn_unused_macros = 0;
    458 
    459     /* Define all of the macros for new options that were just turned on.  */
    460     cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
    461     s390_cpu_cpp_builtins_internal (parse_in, cur_opt, prev_opt);
    462     cpp_stop_forcing_token_locations (parse_in);
    463 
    464     cpp_opts->warn_unused_macros = saved_warn_unused_macros;
    465   }
    466 
    467   return true;
    468 }
    469 #endif
    470 
    471 /* Expand builtins which can directly be mapped to tree expressions.
    472    LOC - location information
    473    FCODE - function code of the builtin
    474    ARGLIST - value supposed to be passed as arguments
    475    RETURN-TYPE - expected return type of the builtin */
    476 static tree
    477 s390_expand_overloaded_builtin (location_t loc,
    478 				unsigned fcode,
    479 				vec<tree, va_gc> *arglist,
    480 				tree return_type)
    481 {
    482   switch (fcode)
    483     {
    484     case S390_OVERLOADED_BUILTIN_s390_vec_step:
    485       if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
    486 	{
    487 	  error_at (loc, "builtin %qs can only be used on vector types",
    488 		    "vec_step");
    489 	  return error_mark_node;
    490 	}
    491       return build_int_cst (NULL_TREE,
    492 			    TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
    493     case S390_OVERLOADED_BUILTIN_s390_vec_xl:
    494     case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
    495     case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
    496       {
    497 	/* Build a vector type with the alignment of the source
    498 	   location in order to enable correct alignment hints to be
    499 	   generated for vl.  */
    500 	unsigned align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[1])));
    501 	tree mem_type = build_aligned_type (return_type, align);
    502 	return build2 (MEM_REF, mem_type,
    503 		       fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
    504 		       build_int_cst (ptr_type_node, 0));
    505       }
    506     case S390_OVERLOADED_BUILTIN_s390_vec_xst:
    507     case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
    508     case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
    509       {
    510 	/* Build a vector type with the alignment of the target
    511 	   location in order to enable correct alignment hints to be
    512 	   generated for vst.  */
    513 	unsigned align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[2])));
    514 	tree mem_type = build_aligned_type (TREE_TYPE ((*arglist)[0]), align);
    515 	return build2 (MODIFY_EXPR, mem_type,
    516 		       build2 (MEM_REF, mem_type,
    517 			       fold_build_pointer_plus ((*arglist)[2],
    518 							(*arglist)[1]),
    519 			       build_int_cst (ptr_type_node, 0)),
    520 		       (*arglist)[0]);
    521       }
    522     case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
    523       return build_constructor_va (return_type, 2,
    524 				   NULL_TREE, (*arglist)[0],
    525 				   NULL_TREE, (*arglist)[1]);
    526     default:
    527       gcc_unreachable ();
    528     }
    529 }
    530 
    531 /* invert result */
    532 #define __VSTRING_FLAG_IN         8
    533 /* result type */
    534 #define __VSTRING_FLAG_RT         4
    535 /* zero search */
    536 #define __VSTRING_FLAG_ZS         2
    537 /* set condition code */
    538 #define __VSTRING_FLAG_CS         1
    539 
    540 /* Return the flags value to be used for string low-level builtins
    541    when expanded from overloaded builtin OB_FCODE.  */
    542 static unsigned int
    543 s390_get_vstring_flags (int ob_fcode)
    544 {
    545   unsigned int flags = 0;
    546 
    547   switch (ob_fcode)
    548     {
    549     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
    550     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
    551     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
    552     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
    553     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
    554     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
    555     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
    556     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
    557     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
    558     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
    559     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
    560     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
    561       flags |= __VSTRING_FLAG_IN;
    562       break;
    563     default:
    564       break;
    565     }
    566   switch (ob_fcode)
    567     {
    568 
    569     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
    570     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
    571     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
    572     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
    573     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
    574     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
    575     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
    576     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
    577       flags |= __VSTRING_FLAG_RT;
    578       break;
    579     default:
    580       break;
    581     }
    582   switch (ob_fcode)
    583     {
    584 
    585     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
    586     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
    587     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
    588     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
    589     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
    590     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
    591     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
    592     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
    593       flags |= __VSTRING_FLAG_ZS;
    594       break;
    595     default:
    596       break;
    597     }
    598   switch (ob_fcode)
    599     {
    600     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
    601     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
    602     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
    603     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
    604     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
    605     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
    606     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
    607     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
    608     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
    609     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
    610     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
    611     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
    612       flags |= __VSTRING_FLAG_CS;
    613       break;
    614     default:
    615       break;
    616     }
    617   return flags;
    618 }
    619 #undef __VSTRING_FLAG_IN
    620 #undef __VSTRING_FLAG_RT
    621 #undef __VSTRING_FLAG_ZS
    622 #undef __VSTRING_FLAG_CS
    623 
    624 /* For several overloaded builtins the argument lists do not match
    625    exactly the signature of a low-level builtin.  This function
    626    adjusts the argument list ARGLIST for the overloaded builtin
    627    OB_FCODE to the signature of the low-level builtin given by
    628    DECL.  */
    629 static void
    630 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
    631 			     vec<tree, va_gc> **arglist)
    632 {
    633   tree arg_chain;
    634   int src_arg_index, dest_arg_index;
    635   vec<tree, va_gc> *folded_args = NULL;
    636 
    637   /* We at most add one more operand to the list.  */
    638   vec_alloc (folded_args, (*arglist)->allocated () + 1);
    639   for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
    640 	 src_arg_index = 0, dest_arg_index = 0;
    641        !VOID_TYPE_P (TREE_VALUE (arg_chain));
    642        arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
    643     {
    644       bool arg_assigned_p = false;
    645       switch (ob_fcode)
    646 	{
    647 	  /* For all these the low level builtin needs an additional flags parameter.  */
    648 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
    649 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
    650 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
    651 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
    652 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
    653 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
    654 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
    655 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
    656 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
    657 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
    658 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
    659 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
    660 	  if (dest_arg_index == 2)
    661 	    {
    662 	      folded_args->quick_push (build_int_cst (integer_type_node,
    663 				       s390_get_vstring_flags (ob_fcode)));
    664 	      arg_assigned_p = true;
    665 	    }
    666 	  break;
    667 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
    668 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
    669 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
    670 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
    671 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
    672 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
    673 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
    674 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
    675 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
    676 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
    677 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
    678 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
    679 	  if (dest_arg_index == 3)
    680 	    {
    681 	      folded_args->quick_push (build_int_cst (integer_type_node,
    682 				       s390_get_vstring_flags (ob_fcode)));
    683 	      arg_assigned_p = true;
    684 	    }
    685 	  break;
    686 	case S390_OVERLOADED_BUILTIN_s390_vec_sel:
    687 	case S390_OVERLOADED_BUILTIN_s390_vec_insert:
    688 	case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
    689 	  /* Swap the first to arguments. It is better to do it here
    690 	     instead of the header file to avoid operand checking
    691 	     throwing error messages for a weird operand index.  */
    692 	  if (dest_arg_index < 2)
    693 	    {
    694 	      folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
    695 					 (**arglist)[1 - dest_arg_index]));
    696 	      src_arg_index++;
    697 	      arg_assigned_p = true;
    698 	    }
    699 	  break;
    700 	case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
    701 	  if (dest_arg_index == 1 || dest_arg_index == 2)
    702 	    {
    703 	      folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
    704 					 (**arglist)[3 - dest_arg_index]));
    705 	      src_arg_index++;
    706 	      arg_assigned_p = true;
    707 	    }
    708 	  break;
    709 
    710 	case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
    711 	  {
    712 	    int code;
    713 	    if (dest_arg_index == 1)
    714 	      {
    715 		tree arg = (**arglist)[src_arg_index];
    716 
    717 		if (TREE_CODE (arg) != INTEGER_CST)
    718 		  {
    719 		    error ("constant value required for builtin %qF argument %d",
    720 			   decl, src_arg_index + 1);
    721 		    return;
    722 		  }
    723 
    724 		switch (tree_to_uhwi (arg))
    725 		  {
    726 		  case 64: code = 0; break;
    727 		  case 128: code = 1; break;
    728 		  case 256: code = 2; break;
    729 		  case 512: code = 3; break;
    730 		  case 1024: code = 4; break;
    731 		  case 2048: code = 5; break;
    732 		  case 4096: code = 6; break;
    733 		  default:
    734 		    error ("valid values for builtin %qF argument %d are 64, "
    735 			   "128, 256, 512, 1024, 2048, and 4096", decl,
    736 			   src_arg_index + 1);
    737 		    return;
    738 		  }
    739 		folded_args->quick_push (build_int_cst (integer_type_node,
    740 							code));
    741 		src_arg_index++;
    742 		arg_assigned_p = true;
    743 	      }
    744 	  }
    745 	  break;
    746 	case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
    747 	  /* Duplicate the first src arg.  */
    748 	  if (dest_arg_index == 0)
    749 	    {
    750 	      folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
    751 					   (**arglist)[src_arg_index]));
    752 	      arg_assigned_p = true;
    753 	    }
    754 	  break;
    755 	default:
    756 	  break;
    757 	}
    758       if (!arg_assigned_p)
    759 	{
    760 	  folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
    761 						 (**arglist)[src_arg_index]));
    762 	  src_arg_index++;
    763 	}
    764     }
    765   *arglist = folded_args;
    766 }
    767 
    768 /* Check whether the arguments in ARGLIST match the function type
    769    DEF_TYPE. Return the number of argument types which required
    770    conversion/promotion in order to make it match.
    771    0 stands for a perfect match - all operand types match without changes
    772    INT_MAX stands for a mismatch.  */
    773 static int
    774 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
    775 			  vec<tree, va_gc> *arglist)
    776 {
    777   unsigned int i;
    778   int match_type = 0;
    779 
    780   for (i = 0; i < vec_safe_length (arglist); i++)
    781     {
    782       tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
    783       tree in_arg = (*arglist)[i];
    784       tree in_type = TREE_TYPE (in_arg);
    785 
    786       if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
    787 	{
    788 	  /* Vector types have to match precisely.  */
    789 	  if (b_arg_type != in_type
    790 	      && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
    791 	    goto mismatch;
    792 	}
    793 
    794       if (lang_hooks.types_compatible_p (in_type, b_arg_type))
    795 	continue;
    796 
    797       if (lang_hooks.types_compatible_p (
    798 	    lang_hooks.types.type_promotes_to (in_type),
    799 	    lang_hooks.types.type_promotes_to (b_arg_type)))
    800 	{
    801 	  match_type++;
    802 	  continue;
    803 	}
    804 
    805       /* In this stage the C++ frontend would go ahead trying to find
    806 	 implicit conversion chains for the argument to match the
    807 	 target type.  We will mimic this here only for our limited
    808 	 subset of argument types.  */
    809       if (TREE_CODE (b_arg_type) == INTEGER_TYPE
    810 	  && TREE_CODE (in_type) == INTEGER_TYPE)
    811 	{
    812 	  match_type++;
    813 	  continue;
    814 	}
    815 
    816       /* If the incoming pointer argument has more qualifiers than the
    817 	 argument type it can still be an imperfect match.  */
    818       if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
    819 	  && !(TYPE_QUALS (TREE_TYPE (in_type))
    820 	       & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
    821 	  && (TYPE_QUALS (TREE_TYPE (b_arg_type))
    822 	      & ~TYPE_QUALS (TREE_TYPE (in_type))))
    823 	{
    824 	  tree qual_in_type =
    825 	    build_qualified_type (TREE_TYPE (in_type),
    826 				  TYPE_QUALS (TREE_TYPE (b_arg_type)));
    827 
    828 	  if (lang_hooks.types_compatible_p (qual_in_type,
    829 					     TREE_TYPE (b_arg_type)))
    830 	    {
    831 	      match_type++;
    832 	      continue;
    833 	    }
    834 	}
    835 
    836     mismatch:
    837       if (TARGET_DEBUG_ARG)
    838 	{
    839 	  fprintf (stderr, " mismatch in operand: %d incoming: ", i + 1);
    840 	  print_generic_expr (stderr, in_type, TDF_VOPS|TDF_MEMSYMS);
    841 	  fprintf (stderr, " expected: ");
    842 	  print_generic_expr (stderr, b_arg_type, TDF_VOPS|TDF_MEMSYMS);
    843 	  fprintf (stderr, "\n");
    844 	}
    845       return INT_MAX;
    846     }
    847 
    848   return match_type;
    849 }
    850 
    851 /* Return the number of elements in the vector arguments of FNDECL in
    852    case all it matches for all vector arguments, -1 otherwise.  */
    853 static int
    854 s390_vec_n_elem (tree fndecl)
    855 {
    856   tree b_arg_chain;
    857   int n_elem = -1;
    858 
    859   if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) == VECTOR_TYPE)
    860     n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
    861 
    862   for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
    863        !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
    864        b_arg_chain = TREE_CHAIN (b_arg_chain))
    865     {
    866       int tmp_n_elem;
    867       if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
    868 	continue;
    869       tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
    870       if (n_elem != -1 && n_elem != tmp_n_elem)
    871 	return -1;
    872       n_elem = tmp_n_elem;
    873     }
    874   return n_elem;
    875 }
    876 
    877 
    878 /* Return a tree expression for a call to the overloaded builtin
    879    function OB_FNDECL at LOC with arguments PASSED_ARGLIST.  */
    880 tree
    881 s390_resolve_overloaded_builtin (location_t loc,
    882 				 tree ob_fndecl,
    883 				 void *passed_arglist)
    884 {
    885   vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
    886   unsigned int in_args_num = vec_safe_length (arglist);
    887   unsigned int ob_args_num = 0;
    888   unsigned int ob_fcode = DECL_MD_FUNCTION_CODE (ob_fndecl);
    889   enum s390_overloaded_builtin_vars bindex;
    890   unsigned int i;
    891   int last_match_type = INT_MAX;
    892   int last_match_index = -1;
    893   unsigned int all_op_flags;
    894   const unsigned int ob_flags = bflags_for_builtin(ob_fcode);
    895   int num_matches = 0;
    896   tree target_builtin_decl, b_arg_chain, return_type;
    897   enum s390_builtin_ov_type_index last_match_fntype_index = BT_OV_MAX;
    898 
    899   if (TARGET_DEBUG_ARG)
    900     fprintf (stderr,
    901       "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
    902       (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
    903      ob_fcode < S390_BUILTIN_MAX ? "not" : "");
    904 
    905   /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins.  */
    906   if (ob_fcode < S390_BUILTIN_MAX)
    907     {
    908       if (ob_flags & B_INT)
    909 	{
    910 	  error_at (loc,
    911 		    "builtin %qF is for GCC internal use only",
    912 		    ob_fndecl);
    913 	  return error_mark_node;
    914 	}
    915       return NULL_TREE;
    916     }
    917 
    918   if (ob_flags & B_DEP)
    919     warning_at (loc, 0, "builtin %qF is deprecated", ob_fndecl);
    920 
    921   if (!TARGET_VX && (ob_flags & B_VX))
    922     {
    923       error_at (loc, "%qF requires %<-mvx%>", ob_fndecl);
    924       return error_mark_node;
    925     }
    926 
    927   if (!TARGET_VXE && (ob_flags & B_VXE))
    928     {
    929       error_at (loc, "%qF requires z14 or higher", ob_fndecl);
    930       return error_mark_node;
    931     }
    932 
    933   if (!TARGET_VXE2 && (ob_flags & B_VXE2))
    934     {
    935       error_at (loc, "%qF requires z15 or higher", ob_fndecl);
    936       return error_mark_node;
    937     }
    938 
    939   ob_fcode -= S390_BUILTIN_MAX;
    940 
    941   for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
    942        !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
    943        b_arg_chain = TREE_CHAIN (b_arg_chain))
    944     ob_args_num++;
    945 
    946   if (ob_args_num != in_args_num)
    947     {
    948       error_at (loc,
    949 		"mismatch in number of arguments for builtin %qF. "
    950 		"Expected: %d got %d", ob_fndecl,
    951 		ob_args_num, in_args_num);
    952       return error_mark_node;
    953     }
    954 
    955   for (i = 0; i < in_args_num; i++)
    956     if ((*arglist)[i] == error_mark_node)
    957       return error_mark_node;
    958 
    959   /* Overloaded builtins without any variants are directly expanded here.  */
    960   if (desc_start_for_overloaded_builtin[ob_fcode] ==
    961       S390_OVERLOADED_BUILTIN_VAR_MAX)
    962     return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
    963 
    964   for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
    965        bindex <= desc_end_for_overloaded_builtin[ob_fcode];
    966        bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
    967   {
    968     int match_type;
    969     enum s390_builtin_ov_type_index type_index =
    970       type_for_overloaded_builtin_var[bindex];
    971 
    972     if (TARGET_DEBUG_ARG)
    973       fprintf (stderr, "checking variant number: %d", (int)bindex);
    974 
    975     match_type = s390_fn_types_compatible (type_index, arglist);
    976 
    977     if (match_type == INT_MAX)
    978       continue;
    979 
    980     if (TARGET_DEBUG_ARG)
    981       fprintf (stderr,
    982 	       " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
    983 	       match_type);
    984 
    985     if (match_type < last_match_type)
    986       {
    987 	num_matches = 1;
    988 	last_match_type = match_type;
    989 	last_match_fntype_index = type_index;
    990 	last_match_index = bindex;
    991       }
    992     else if (match_type == last_match_type)
    993       num_matches++;
    994   }
    995 
    996   if (last_match_type == INT_MAX)
    997     {
    998       error_at (loc, "invalid parameter combination for intrinsic %qs",
    999 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
   1000       return error_mark_node;
   1001     }
   1002   else if (num_matches > 1)
   1003     {
   1004       error_at (loc, "ambiguous overload for intrinsic %qs",
   1005 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
   1006       return error_mark_node;
   1007     }
   1008 
   1009   if (!TARGET_VXE
   1010       && bflags_overloaded_builtin_var[last_match_index] & B_VXE)
   1011     {
   1012       error_at (loc, "%qs matching variant requires z14 or higher",
   1013 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
   1014       return error_mark_node;
   1015     }
   1016 
   1017 
   1018   if (!TARGET_VXE2
   1019       && bflags_overloaded_builtin_var[last_match_index] & B_VXE2)
   1020     {
   1021       error_at (loc, "%qs matching variant requires z15 or higher",
   1022 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
   1023       return error_mark_node;
   1024     }
   1025 
   1026   if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
   1027     warning_at (loc, 0, "%qs matching variant is deprecated",
   1028 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
   1029 
   1030   /* Overloaded variants which have MAX set as low level builtin are
   1031      supposed to be replaced during expansion with something else.  */
   1032   if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
   1033     target_builtin_decl = ob_fndecl;
   1034   else
   1035     target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
   1036 
   1037   all_op_flags = opflags_overloaded_builtin_var[last_match_index];
   1038   return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
   1039 
   1040   /* Check for the operand flags in the overloaded builtin variant.  */
   1041   for (i = 0; i < ob_args_num; i++)
   1042     {
   1043       unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
   1044       tree arg = (*arglist)[i];
   1045       tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
   1046 
   1047       all_op_flags = all_op_flags >> O_SHIFT;
   1048 
   1049       if (op_flags == O_ELEM)
   1050 	{
   1051 	  int n_elem = s390_vec_n_elem (target_builtin_decl);
   1052 	  gcc_assert (n_elem > 0);
   1053 	  gcc_assert (type == integer_type_node);
   1054 	  (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
   1055 				  fold_convert (integer_type_node, arg),
   1056 				  build_int_cst (NULL_TREE, n_elem - 1));
   1057 	}
   1058 
   1059       if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
   1060 	continue;
   1061 
   1062       if ((TYPE_UNSIGNED (type)
   1063 	   && !int_fits_type_p (arg, c_common_unsigned_type (type)))
   1064 	  || (!TYPE_UNSIGNED (type)
   1065 	      && !int_fits_type_p (arg, c_common_signed_type (type))))
   1066 	{
   1067 	  error("constant argument %d for builtin %qF is out "
   1068 		"of range for target type",
   1069 		i + 1, target_builtin_decl);
   1070 	  return error_mark_node;
   1071 	}
   1072 
   1073       if (TREE_CODE (arg) == INTEGER_CST
   1074 	  && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
   1075 	return error_mark_node;
   1076     }
   1077 
   1078   /* Handle builtins we expand directly - without mapping it to a low
   1079      level builtin.  */
   1080   if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
   1081     return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
   1082 
   1083   s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
   1084 
   1085   if (VOID_TYPE_P (return_type))
   1086     return build_function_call_vec (loc, vNULL, target_builtin_decl,
   1087 				    arglist, NULL);
   1088   else
   1089     return fully_fold_convert (return_type,
   1090 			       build_function_call_vec (loc, vNULL, target_builtin_decl,
   1091 							arglist, NULL));
   1092 }
   1093 
   1094 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h.  */
   1095 void
   1096 s390_register_target_pragmas (void)
   1097 {
   1098   targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
   1099 #if S390_USE_TARGET_ATTRIBUTE
   1100   /* Update pragma hook to allow parsing #pragma GCC target.  */
   1101   targetm.target_option.pragma_parse = s390_pragma_target_parse;
   1102 #endif
   1103 }
   1104