xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/s390/s390-c.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Language specific subroutines used for code generation on IBM S/390
2    and zSeries
3    Copyright (C) 2015-2020 Free Software Foundation, Inc.
4 
5    Contributed by Andreas Krebbel (Andreas.Krebbel@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.c.
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
fully_fold_convert(tree type,tree expr)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 *
s390_categorize_keyword(const cpp_token * tok)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 *
s390_macro_to_expand(cpp_reader * pfile,const cpp_token * tok)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 static void
s390_def_or_undef_macro(cpp_reader * pfile,unsigned int mask,const struct cl_target_option * old_opts,const struct cl_target_option * new_opts,const char * macro_def,const char * macro_undef)298 s390_def_or_undef_macro (cpp_reader *pfile,
299 			 unsigned int mask,
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 : old_opts->x_target_flags & mask;
308   set = new_opts->x_target_flags & mask;
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 /* Internal function to either define or undef the appropriate system
318    macros.  */
319 static void
s390_cpu_cpp_builtins_internal(cpp_reader * pfile,struct cl_target_option * opts,const struct cl_target_option * old_opts)320 s390_cpu_cpp_builtins_internal (cpp_reader *pfile,
321 				struct cl_target_option *opts,
322 				const struct cl_target_option *old_opts)
323 {
324   s390_def_or_undef_macro (pfile, MASK_OPT_HTM, old_opts, opts,
325 			   "__HTM__", "__HTM__");
326   s390_def_or_undef_macro (pfile, MASK_OPT_VX, old_opts, opts,
327 			   "__VX__", "__VX__");
328   s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
329 			   "__VEC__=10303", "__VEC__");
330   s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
331 			   "__vector=__attribute__((vector_size(16)))",
332 			   "__vector__");
333   s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
334 			   "__bool=__attribute__((s390_vector_bool)) unsigned",
335 			   "__bool");
336   {
337     char macro_def[64];
338     gcc_assert (s390_arch != PROCESSOR_NATIVE);
339     sprintf (macro_def, "__ARCH__=%d", processor_table[s390_arch].arch_level);
340     cpp_undef (pfile, "__ARCH__");
341     cpp_define (pfile, macro_def);
342   }
343 
344   if (!flag_iso)
345     {
346       s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
347 			       "__VECTOR_KEYWORD_SUPPORTED__",
348 			       "__VECTOR_KEYWORD_SUPPORTED__");
349       s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
350 			       "vector=vector", "vector");
351       s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
352 			       "bool=bool", "bool");
353       if (TARGET_ZVECTOR_P (opts->x_target_flags) && __vector_keyword == NULL)
354 	{
355 	  __vector_keyword = get_identifier ("__vector");
356 	  C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
357 
358 	  vector_keyword = get_identifier ("vector");
359 	  C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
360 
361 	  __bool_keyword = get_identifier ("__bool");
362 	  C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
363 
364 	  bool_keyword = get_identifier ("bool");
365 	  C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
366 
367 	  _Bool_keyword = get_identifier ("_Bool");
368 	  C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
369 
370 	  /* Enable context-sensitive macros.  */
371 	  cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
372 	}
373     }
374 }
375 
376 /* Define platform dependent macros.  */
377 void
s390_cpu_cpp_builtins(cpp_reader * pfile)378 s390_cpu_cpp_builtins (cpp_reader *pfile)
379 {
380   struct cl_target_option opts;
381 
382   cpp_assert (pfile, "cpu=s390");
383   cpp_assert (pfile, "machine=s390");
384   cpp_define (pfile, "__s390__");
385   if (TARGET_ZARCH)
386     cpp_define (pfile, "__zarch__");
387   if (TARGET_64BIT)
388     cpp_define (pfile, "__s390x__");
389   if (TARGET_LONG_DOUBLE_128)
390     cpp_define (pfile, "__LONG_DOUBLE_128__");
391   cl_target_option_save (&opts, &global_options);
392   s390_cpu_cpp_builtins_internal (pfile, &opts, NULL);
393 }
394 
395 #if S390_USE_TARGET_ATTRIBUTE
396 /* Hook to validate the current #pragma GCC target and set the state, and
397    update the macros based on what was changed.  If ARGS is NULL, then
398    POP_TARGET is used to reset the options.  */
399 
400 static bool
s390_pragma_target_parse(tree args,tree pop_target)401 s390_pragma_target_parse (tree args, tree pop_target)
402 {
403   tree prev_tree = build_target_option_node (&global_options);
404   tree cur_tree;
405 
406   if (! args)
407     cur_tree = pop_target;
408   else
409     {
410       cur_tree = s390_valid_target_attribute_tree (args, &global_options,
411 						   &global_options_set, true);
412       if (!cur_tree || cur_tree == error_mark_node)
413 	{
414 	  cl_target_option_restore (&global_options,
415 				    TREE_TARGET_OPTION (prev_tree));
416 	  return false;
417 	}
418     }
419 
420   target_option_current_node = cur_tree;
421   s390_activate_target_options (target_option_current_node);
422 
423   {
424     struct cl_target_option *prev_opt;
425     struct cl_target_option *cur_opt;
426 
427     /* Figure out the previous/current differences.  */
428     prev_opt = TREE_TARGET_OPTION (prev_tree);
429     cur_opt = TREE_TARGET_OPTION (cur_tree);
430 
431     /* For the definitions, ensure all newly defined macros are considered
432        as used for -Wunused-macros.  There is no point warning about the
433        compiler predefined macros.  */
434     cpp_options *cpp_opts = cpp_get_options (parse_in);
435     unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
436 
437     cpp_opts->warn_unused_macros = 0;
438 
439     /* Define all of the macros for new options that were just turned on.  */
440     s390_cpu_cpp_builtins_internal (parse_in, cur_opt, prev_opt);
441 
442     cpp_opts->warn_unused_macros = saved_warn_unused_macros;
443   }
444 
445   return true;
446 }
447 #endif
448 
449 /* Expand builtins which can directly be mapped to tree expressions.
450    LOC - location information
451    FCODE - function code of the builtin
452    ARGLIST - value supposed to be passed as arguments
453    RETURN-TYPE - expected return type of the builtin */
454 static tree
s390_expand_overloaded_builtin(location_t loc,unsigned fcode,vec<tree,va_gc> * arglist,tree return_type)455 s390_expand_overloaded_builtin (location_t loc,
456 				unsigned fcode,
457 				vec<tree, va_gc> *arglist,
458 				tree return_type)
459 {
460   switch (fcode)
461     {
462     case S390_OVERLOADED_BUILTIN_s390_vec_step:
463       if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
464 	{
465 	  error_at (loc, "builtin vec_step can only be used on vector types.");
466 	  return error_mark_node;
467 	}
468       return build_int_cst (NULL_TREE,
469 			    TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
470     case S390_OVERLOADED_BUILTIN_s390_vec_xl:
471     case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
472     case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
473       {
474 	/* Build a vector type with the alignment of the source
475 	   location in order to enable correct alignment hints to be
476 	   generated for vl.  */
477 	tree mem_type = build_aligned_type (return_type,
478 					    TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[1]))));
479 	return build2 (MEM_REF, mem_type,
480 		       fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
481 		       build_int_cst (TREE_TYPE ((*arglist)[1]), 0));
482       }
483     case S390_OVERLOADED_BUILTIN_s390_vec_xst:
484     case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
485     case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
486       {
487 	/* Build a vector type with the alignment of the target
488 	   location in order to enable correct alignment hints to be
489 	   generated for vst.  */
490 	tree mem_type = build_aligned_type (TREE_TYPE((*arglist)[0]),
491 					    TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[2]))));
492 	return build2 (MODIFY_EXPR, mem_type,
493 		       build1 (INDIRECT_REF, mem_type,
494 			       fold_build_pointer_plus ((*arglist)[2], (*arglist)[1])),
495 		       (*arglist)[0]);
496       }
497     case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
498       return build_constructor_va (return_type, 2,
499 				   NULL_TREE, (*arglist)[0],
500 				   NULL_TREE, (*arglist)[1]);
501     default:
502       gcc_unreachable ();
503     }
504 }
505 
506 /* invert result */
507 #define __VSTRING_FLAG_IN         8
508 /* result type */
509 #define __VSTRING_FLAG_RT         4
510 /* zero search */
511 #define __VSTRING_FLAG_ZS         2
512 /* set condition code */
513 #define __VSTRING_FLAG_CS         1
514 
515 /* Return the flags value to be used for string low-level builtins
516    when expanded from overloaded builtin OB_FCODE.  */
517 static unsigned int
s390_get_vstring_flags(int ob_fcode)518 s390_get_vstring_flags (int ob_fcode)
519 {
520   unsigned int flags = 0;
521 
522   switch (ob_fcode)
523     {
524     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
525     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
526     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
527     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
528     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
529     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
530     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
531     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
532     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
533     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
534     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
535     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
536       flags |= __VSTRING_FLAG_IN;
537       break;
538     default:
539       break;
540     }
541   switch (ob_fcode)
542     {
543 
544     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
545     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
546     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
547     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
548     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
549     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
550     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
551     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
552       flags |= __VSTRING_FLAG_RT;
553       break;
554     default:
555       break;
556     }
557   switch (ob_fcode)
558     {
559 
560     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
561     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
562     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
563     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
564     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
565     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
566     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
567     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
568       flags |= __VSTRING_FLAG_ZS;
569       break;
570     default:
571       break;
572     }
573   switch (ob_fcode)
574     {
575     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
576     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
577     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
578     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
579     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
580     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
581     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
582     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
583     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
584     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
585     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
586     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
587       flags |= __VSTRING_FLAG_CS;
588       break;
589     default:
590       break;
591     }
592   return flags;
593 }
594 #undef __VSTRING_FLAG_IN
595 #undef __VSTRING_FLAG_RT
596 #undef __VSTRING_FLAG_ZS
597 #undef __VSTRING_FLAG_CS
598 
599 /* For several overloaded builtins the argument lists do not match
600    exactly the signature of a low-level builtin.  This function
601    adjusts the argument list ARGLIST for the overloaded builtin
602    OB_FCODE to the signature of the low-level builtin given by
603    DECL.  */
604 static void
s390_adjust_builtin_arglist(unsigned int ob_fcode,tree decl,vec<tree,va_gc> ** arglist)605 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
606 			     vec<tree, va_gc> **arglist)
607 {
608   tree arg_chain;
609   int src_arg_index, dest_arg_index;
610   vec<tree, va_gc> *folded_args = NULL;
611 
612   /* We at most add one more operand to the list.  */
613   vec_alloc (folded_args, (*arglist)->allocated () + 1);
614   for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
615 	 src_arg_index = 0, dest_arg_index = 0;
616        !VOID_TYPE_P (TREE_VALUE (arg_chain));
617        arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
618     {
619       bool arg_assigned_p = false;
620       switch (ob_fcode)
621 	{
622 	  /* For all these the low level builtin needs an additional flags parameter.  */
623 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
624 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
625 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
626 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
627 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
628 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
629 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
630 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
631 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
632 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
633 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
634 	case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
635 	  if (dest_arg_index == 2)
636 	    {
637 	      folded_args->quick_push (build_int_cst (integer_type_node,
638 				       s390_get_vstring_flags (ob_fcode)));
639 	      arg_assigned_p = true;
640 	    }
641 	  break;
642 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
643 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
644 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
645 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
646 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
647 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
648 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
649 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
650 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
651 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
652 	case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
653 	case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
654 	  if (dest_arg_index == 3)
655 	    {
656 	      folded_args->quick_push (build_int_cst (integer_type_node,
657 				       s390_get_vstring_flags (ob_fcode)));
658 	      arg_assigned_p = true;
659 	    }
660 	  break;
661 	case S390_OVERLOADED_BUILTIN_s390_vec_sel:
662 	case S390_OVERLOADED_BUILTIN_s390_vec_insert:
663 	case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
664 	  /* Swap the first to arguments. It is better to do it here
665 	     instead of the header file to avoid operand checking
666 	     throwing error messages for a weird operand index.  */
667 	  if (dest_arg_index < 2)
668 	    {
669 	      folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
670 					 (**arglist)[1 - dest_arg_index]));
671 	      src_arg_index++;
672 	      arg_assigned_p = true;
673 	    }
674 	  break;
675 	case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
676 	  if (dest_arg_index == 1 || dest_arg_index == 2)
677 	    {
678 	      folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
679 					 (**arglist)[3 - dest_arg_index]));
680 	      src_arg_index++;
681 	      arg_assigned_p = true;
682 	    }
683 	  break;
684 
685 	case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
686 	  {
687 	    int code;
688 	    if (dest_arg_index == 1)
689 	      {
690 		tree arg = (**arglist)[src_arg_index];
691 
692 		if (TREE_CODE (arg) != INTEGER_CST)
693 		  {
694 		    error ("constant value required for builtin %qF argument %d",
695 			   decl, src_arg_index + 1);
696 		    return;
697 		  }
698 
699 		switch (tree_to_uhwi (arg))
700 		  {
701 		  case 64: code = 0; break;
702 		  case 128: code = 1; break;
703 		  case 256: code = 2; break;
704 		  case 512: code = 3; break;
705 		  case 1024: code = 4; break;
706 		  case 2048: code = 5; break;
707 		  case 4096: code = 6; break;
708 		  default:
709 		    error ("valid values for builtin %qF argument %d are 64, "
710 			   "128, 256, 512, 1024, 2048, and 4096", decl,
711 			   src_arg_index + 1);
712 		    return;
713 		  }
714 		folded_args->quick_push (build_int_cst (integer_type_node,
715 							code));
716 		src_arg_index++;
717 		arg_assigned_p = true;
718 	      }
719 	  }
720 	  break;
721 	case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
722 	  /* Duplicate the first src arg.  */
723 	  if (dest_arg_index == 0)
724 	    {
725 	      folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
726 					   (**arglist)[src_arg_index]));
727 	      arg_assigned_p = true;
728 	    }
729 	  break;
730 	default:
731 	  break;
732 	}
733       if (!arg_assigned_p)
734 	{
735 	  folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
736 						 (**arglist)[src_arg_index]));
737 	  src_arg_index++;
738 	}
739     }
740   *arglist = folded_args;
741 }
742 
743 /* Check whether the arguments in ARGLIST match the function type
744    DEF_TYPE. Return the number of argument types which required
745    conversion/promotion in order to make it match.
746    0 stands for a perfect match - all operand types match without changes
747    INT_MAX stands for a mismatch.  */
748 static int
s390_fn_types_compatible(enum s390_builtin_ov_type_index typeindex,vec<tree,va_gc> * arglist)749 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
750 			  vec<tree, va_gc> *arglist)
751 {
752   unsigned int i;
753   int match_type = 0;
754 
755   for (i = 0; i < vec_safe_length (arglist); i++)
756     {
757       tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
758       tree in_arg = (*arglist)[i];
759       tree in_type = TREE_TYPE (in_arg);
760 
761       if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
762 	{
763 	  /* Vector types have to match precisely.  */
764 	  if (b_arg_type != in_type
765 	      && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
766 	    goto mismatch;
767 	}
768 
769       if (lang_hooks.types_compatible_p (in_type, b_arg_type))
770 	continue;
771 
772       if (lang_hooks.types_compatible_p (
773 	    lang_hooks.types.type_promotes_to (in_type),
774 	    lang_hooks.types.type_promotes_to (b_arg_type)))
775 	{
776 	  match_type++;
777 	  continue;
778 	}
779 
780       /* In this stage the C++ frontend would go ahead trying to find
781 	 implicit conversion chains for the argument to match the
782 	 target type.  We will mimic this here only for our limited
783 	 subset of argument types.  */
784       if (TREE_CODE (b_arg_type) == INTEGER_TYPE
785 	  && TREE_CODE (in_type) == INTEGER_TYPE)
786 	{
787 	  match_type++;
788 	  continue;
789 	}
790 
791       /* If the incoming pointer argument has more qualifiers than the
792 	 argument type it can still be an imperfect match.  */
793       if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
794 	  && !(TYPE_QUALS (TREE_TYPE (in_type))
795 	       & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
796 	  && (TYPE_QUALS (TREE_TYPE (b_arg_type))
797 	      & ~TYPE_QUALS (TREE_TYPE (in_type))))
798 	{
799 	  tree qual_in_type =
800 	    build_qualified_type (TREE_TYPE (in_type),
801 				  TYPE_QUALS (TREE_TYPE (b_arg_type)));
802 
803 	  if (lang_hooks.types_compatible_p (qual_in_type,
804 					     TREE_TYPE (b_arg_type)))
805 	    {
806 	      match_type++;
807 	      continue;
808 	    }
809 	}
810 
811     mismatch:
812       if (TARGET_DEBUG_ARG)
813 	{
814 	  fprintf (stderr, " mismatch in operand: %d incoming: ", i + 1);
815 	  print_generic_expr (stderr, in_type, TDF_VOPS|TDF_MEMSYMS);
816 	  fprintf (stderr, " expected: ");
817 	  print_generic_expr (stderr, b_arg_type, TDF_VOPS|TDF_MEMSYMS);
818 	  fprintf (stderr, "\n");
819 	}
820       return INT_MAX;
821     }
822 
823   return match_type;
824 }
825 
826 /* Return the number of elements in the vector arguments of FNDECL in
827    case all it matches for all vector arguments, -1 otherwise.  */
828 static int
s390_vec_n_elem(tree fndecl)829 s390_vec_n_elem (tree fndecl)
830 {
831   tree b_arg_chain;
832   int n_elem = -1;
833 
834   if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) == VECTOR_TYPE)
835     n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
836 
837   for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
838        !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
839        b_arg_chain = TREE_CHAIN (b_arg_chain))
840     {
841       int tmp_n_elem;
842       if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
843 	continue;
844       tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
845       if (n_elem != -1 && n_elem != tmp_n_elem)
846 	return -1;
847       n_elem = tmp_n_elem;
848     }
849   return n_elem;
850 }
851 
852 
853 /* Return a tree expression for a call to the overloaded builtin
854    function OB_FNDECL at LOC with arguments PASSED_ARGLIST.  */
855 tree
s390_resolve_overloaded_builtin(location_t loc,tree ob_fndecl,void * passed_arglist)856 s390_resolve_overloaded_builtin (location_t loc,
857 				 tree ob_fndecl,
858 				 void *passed_arglist)
859 {
860   vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
861   unsigned int in_args_num = vec_safe_length (arglist);
862   unsigned int ob_args_num = 0;
863   unsigned int ob_fcode = DECL_MD_FUNCTION_CODE (ob_fndecl);
864   enum s390_overloaded_builtin_vars bindex;
865   unsigned int i;
866   int last_match_type = INT_MAX;
867   int last_match_index = -1;
868   unsigned int all_op_flags;
869   const unsigned int ob_flags = bflags_for_builtin(ob_fcode);
870   int num_matches = 0;
871   tree target_builtin_decl, b_arg_chain, return_type;
872   enum s390_builtin_ov_type_index last_match_fntype_index = BT_OV_MAX;
873 
874   if (TARGET_DEBUG_ARG)
875     fprintf (stderr,
876       "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
877       (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
878      ob_fcode < S390_BUILTIN_MAX ? "not" : "");
879 
880   /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins.  */
881   if (ob_fcode < S390_BUILTIN_MAX)
882     {
883       if (ob_flags & B_INT)
884 	{
885 	  error_at (loc,
886 		    "builtin %qF is for GCC internal use only.",
887 		    ob_fndecl);
888 	  return error_mark_node;
889 	}
890       return NULL_TREE;
891     }
892 
893   if (ob_flags & B_DEP)
894     warning_at (loc, 0, "builtin %qF is deprecated.", ob_fndecl);
895 
896   if (!TARGET_VX && (ob_flags & B_VX))
897     {
898       error_at (loc, "%qF requires %<-mvx%>", ob_fndecl);
899       return error_mark_node;
900     }
901 
902   if (!TARGET_VXE && (ob_flags & B_VXE))
903     {
904       error_at (loc, "%qF requires z14 or higher", ob_fndecl);
905       return error_mark_node;
906     }
907 
908   if (!TARGET_VXE2 && (ob_flags & B_VXE2))
909     {
910       error_at (loc, "%qF requires z15 or higher", ob_fndecl);
911       return error_mark_node;
912     }
913 
914   ob_fcode -= S390_BUILTIN_MAX;
915 
916   for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
917        !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
918        b_arg_chain = TREE_CHAIN (b_arg_chain))
919     ob_args_num++;
920 
921   if (ob_args_num != in_args_num)
922     {
923       error_at (loc,
924 		"mismatch in number of arguments for builtin %qF. "
925 		"Expected: %d got %d", ob_fndecl,
926 		ob_args_num, in_args_num);
927       return error_mark_node;
928     }
929 
930   for (i = 0; i < in_args_num; i++)
931     if ((*arglist)[i] == error_mark_node)
932       return error_mark_node;
933 
934   /* Overloaded builtins without any variants are directly expanded here.  */
935   if (desc_start_for_overloaded_builtin[ob_fcode] ==
936       S390_OVERLOADED_BUILTIN_VAR_MAX)
937     return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
938 
939   for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
940        bindex <= desc_end_for_overloaded_builtin[ob_fcode];
941        bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
942   {
943     int match_type;
944     enum s390_builtin_ov_type_index type_index =
945       type_for_overloaded_builtin_var[bindex];
946 
947     if (TARGET_DEBUG_ARG)
948       fprintf (stderr, "checking variant number: %d", (int)bindex);
949 
950     match_type = s390_fn_types_compatible (type_index, arglist);
951 
952     if (match_type == INT_MAX)
953       continue;
954 
955     if (TARGET_DEBUG_ARG)
956       fprintf (stderr,
957 	       " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
958 	       match_type);
959 
960     if (match_type < last_match_type)
961       {
962 	num_matches = 1;
963 	last_match_type = match_type;
964 	last_match_fntype_index = type_index;
965 	last_match_index = bindex;
966       }
967     else if (match_type == last_match_type)
968       num_matches++;
969   }
970 
971   if (last_match_type == INT_MAX)
972     {
973       error_at (loc, "invalid parameter combination for intrinsic %qs",
974 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
975       return error_mark_node;
976     }
977   else if (num_matches > 1)
978     {
979       error_at (loc, "ambiguous overload for intrinsic %qs",
980 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
981       return error_mark_node;
982     }
983 
984   if (!TARGET_VXE
985       && bflags_overloaded_builtin_var[last_match_index] & B_VXE)
986     {
987       error_at (loc, "%qs matching variant requires z14 or higher",
988 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
989       return error_mark_node;
990     }
991 
992 
993   if (!TARGET_VXE2
994       && bflags_overloaded_builtin_var[last_match_index] & B_VXE2)
995     {
996       error_at (loc, "%qs matching variant requires z15 or higher",
997 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
998       return error_mark_node;
999     }
1000 
1001   if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
1002     warning_at (loc, 0, "%qs matching variant is deprecated.",
1003 		IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1004 
1005   /* Overloaded variants which have MAX set as low level builtin are
1006      supposed to be replaced during expansion with something else.  */
1007   if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1008     target_builtin_decl = ob_fndecl;
1009   else
1010     target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
1011 
1012   all_op_flags = opflags_overloaded_builtin_var[last_match_index];
1013   return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
1014 
1015   /* Check for the operand flags in the overloaded builtin variant.  */
1016   for (i = 0; i < ob_args_num; i++)
1017     {
1018       unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
1019       tree arg = (*arglist)[i];
1020       tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
1021 
1022       all_op_flags = all_op_flags >> O_SHIFT;
1023 
1024       if (op_flags == O_ELEM)
1025 	{
1026 	  int n_elem = s390_vec_n_elem (target_builtin_decl);
1027 	  gcc_assert (n_elem > 0);
1028 	  gcc_assert (type == integer_type_node);
1029 	  (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
1030 				  fold_convert (integer_type_node, arg),
1031 				  build_int_cst (NULL_TREE, n_elem - 1));
1032 	}
1033 
1034       if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
1035 	continue;
1036 
1037       if ((TYPE_UNSIGNED (type)
1038 	   && !int_fits_type_p (arg, c_common_unsigned_type (type)))
1039 	  || (!TYPE_UNSIGNED (type)
1040 	      && !int_fits_type_p (arg, c_common_signed_type (type))))
1041 	{
1042 	  error("constant argument %d for builtin %qF is out "
1043 		"of range for target type",
1044 		i + 1, target_builtin_decl);
1045 	  return error_mark_node;
1046 	}
1047 
1048       if (TREE_CODE (arg) == INTEGER_CST
1049 	  && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
1050 	return error_mark_node;
1051     }
1052 
1053   /* Handle builtins we expand directly - without mapping it to a low
1054      level builtin.  */
1055   if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1056     return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
1057 
1058   s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
1059 
1060   if (VOID_TYPE_P (return_type))
1061     return build_function_call_vec (loc, vNULL, target_builtin_decl,
1062 				    arglist, NULL);
1063   else
1064     return fully_fold_convert (return_type,
1065 			       build_function_call_vec (loc, vNULL, target_builtin_decl,
1066 							arglist, NULL));
1067 }
1068 
1069 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h.  */
1070 void
s390_register_target_pragmas(void)1071 s390_register_target_pragmas (void)
1072 {
1073   targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
1074 #if S390_USE_TARGET_ATTRIBUTE
1075   /* Update pragma hook to allow parsing #pragma GCC target.  */
1076   targetm.target_option.pragma_parse = s390_pragma_target_parse;
1077 #endif
1078 }
1079