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