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