S/390: Fix RT flag in vstrc instruction.
[platform/upstream/gcc.git] / gcc / config / s390 / s390-c.c
1 /* Language specific subroutines used for code generation on IBM S/390
2    and zSeries
3    Copyright (C) 2015 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 #include "config.h"
31 #include "system.h"
32 #include "coretypes.h"
33 #include "target.h"
34 #include "tree.h"
35 #include "c-family/c-common.h"
36 #include "c/c-tree.h"
37 #include "tm_p.h"
38 #include "stringpool.h"
39 #include "c-family/c-pragma.h"
40 #include "langhooks.h"
41 #include "tree-pretty-print.h"
42
43 #include "s390-builtins.h"
44
45 static GTY(()) tree __vector_keyword;
46 static GTY(()) tree vector_keyword;
47 static GTY(()) tree __bool_keyword;
48 static GTY(()) tree bool_keyword;
49 static GTY(()) tree _Bool_keyword;
50
51
52 /* Generate an array holding all the descriptions of variants of
53    overloaded builtins defined with OB_DEF_VAR in
54    s390-builtins.def.  */
55 static enum s390_builtin_ov_type_index
56 type_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX + 1] =
57   {
58 #undef B_DEF
59 #undef OB_DEF
60 #undef OB_DEF_VAR
61 #define B_DEF(...)
62 #define OB_DEF(...)
63 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, FNTYPE) FNTYPE,
64 #include "s390-builtins.def"
65     BT_OV_MAX
66   };
67
68
69 /* Generate an array indexed by an overloaded builtin index returning
70    the first index in desc_for_overloaded_builtin_var where the
71    variants for the builtin can be found.  */
72 static enum s390_overloaded_builtin_vars
73 desc_start_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
74   {
75 #undef B_DEF
76 #undef OB_DEF
77 #undef OB_DEF_VAR
78 #define B_DEF(...)
79 #define OB_DEF(NAME, FIRST_VAR_NAME,...)        \
80     S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
81 #define OB_DEF_VAR(...)
82     #include "s390-builtins.def"
83     S390_OVERLOADED_BUILTIN_VAR_MAX
84   };
85
86 /* Generate an array indexed by an overloaded builtin index returning
87    the last index in desc_for_overloaded_builtin_var where the
88    variants for the builtin can be found.  */
89 static enum s390_overloaded_builtin_vars
90 desc_end_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
91   {
92 #undef B_DEF
93 #undef OB_DEF
94 #undef OB_DEF_VAR
95 #define B_DEF(...)
96 #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...) \
97     S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
98 #define OB_DEF_VAR(...)
99     #include "s390-builtins.def"
100     S390_OVERLOADED_BUILTIN_VAR_MAX
101   };
102
103 static enum s390_builtin_type_index
104 s390_builtin_ov_types[BT_OV_MAX][MAX_OV_OPERANDS] =
105   {
106 #undef DEF_TYPE
107 #undef DEF_POINTER_TYPE
108 #undef DEF_DISTINCT_TYPE
109 #undef DEF_VECTOR_TYPE
110 #undef DEF_OPAQUE_VECTOR_TYPE
111 #undef DEF_FN_TYPE
112 #undef DEF_OV_TYPE
113 #define DEF_TYPE(...)
114 #define DEF_POINTER_TYPE(...)
115 #define DEF_DISTINCT_TYPE(...)
116 #define DEF_VECTOR_TYPE(...)
117 #define DEF_OPAQUE_VECTOR_TYPE(...)
118 #define DEF_FN_TYPE(...)
119 #define DEF_OV_TYPE(INDEX, args...) { args },
120 #include "s390-builtin-types.def"
121   };
122
123 static const enum s390_builtins
124 bt_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX] = {
125 #undef B_DEF
126 #undef OB_DEF
127 #undef OB_DEF_VAR
128 #define B_DEF(...)
129 #define OB_DEF(...)
130 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
131
132 #include "s390-builtins.def"
133   };
134
135 /* In addition to calling fold_convert for EXPR of type TYPE, also
136    call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
137    hiding there (PR47197).  */
138 tree
139 fully_fold_convert (tree type, tree expr)
140 {
141   tree result = fold_convert (type, expr);
142   bool maybe_const = true;
143
144   if (!c_dialect_cxx ())
145     result = c_fully_fold (result, false, &maybe_const);
146
147   return result;
148 }
149
150 /* Unify the different variants to the same nodes in order to keep the
151    code working with it simple.  */
152 static cpp_hashnode *
153 s390_categorize_keyword (const cpp_token *tok)
154 {
155   if (tok->type == CPP_NAME)
156     {
157       cpp_hashnode *ident = tok->val.node.node;
158
159       if (ident == C_CPP_HASHNODE (vector_keyword))
160         return C_CPP_HASHNODE (__vector_keyword);
161
162       if (ident == C_CPP_HASHNODE (bool_keyword))
163         return C_CPP_HASHNODE (__bool_keyword);
164
165       if (ident == C_CPP_HASHNODE (_Bool_keyword))
166         return C_CPP_HASHNODE (__bool_keyword);
167       return ident;
168     }
169
170   return 0;
171 }
172
173
174 /* Called to decide whether a conditional macro should be expanded.
175    Since we have exactly one such macro (i.e, 'vector'), we do not
176    need to examine the 'tok' parameter.  */
177
178 static cpp_hashnode *
179 s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
180 {
181   cpp_hashnode *expand_this = tok->val.node.node;
182   cpp_hashnode *ident;
183   static bool expand_bool_p = false;
184   int idx = 0;
185   enum rid rid_code;
186
187   /* The vector keyword is only expanded if the machine actually
188      provides hardware support.  */
189   if (!TARGET_ZVECTOR)
190     return NULL;
191
192   ident = s390_categorize_keyword (tok);
193
194   /* Triggered when we picked a different variant in
195      s390_categorize_keyword.  */
196   if (ident != expand_this)
197     expand_this = NULL;
198
199   /* The vector keyword has been found already and we remembered to
200      expand the next bool.  */
201   if (expand_bool_p && ident == C_CPP_HASHNODE (__bool_keyword))
202     {
203       expand_bool_p = false;
204       return ident;
205     }
206
207   if (ident != C_CPP_HASHNODE (__vector_keyword))
208     return expand_this;
209
210   do
211     tok = cpp_peek_token (pfile, idx++);
212   while (tok->type == CPP_PADDING);
213   ident = s390_categorize_keyword (tok);
214
215   if (!ident)
216     return expand_this;
217
218   /* vector bool - remember to expand the next bool. */
219   if (ident == C_CPP_HASHNODE (__bool_keyword))
220     {
221       expand_bool_p = true;
222       return C_CPP_HASHNODE (__vector_keyword);
223     }
224
225   /* The boost libraries have code with Iterator::vector vector in it.
226      If we allow the normal handling, this module will be called
227      recursively, and the vector will be skipped.; */
228   if (ident == C_CPP_HASHNODE (__vector_keyword))
229     return expand_this;
230
231   rid_code = (enum rid)(ident->rid_code);
232
233   if (ident->type == NT_MACRO)
234     {
235       /* Now actually fetch the tokens we "peeked" before and do a
236          lookahead for the next.  */
237       do
238         (void) cpp_get_token (pfile);
239       while (--idx > 0);
240       do
241         tok = cpp_peek_token (pfile, idx++);
242       while (tok->type == CPP_PADDING);
243       ident = s390_categorize_keyword (tok);
244
245       if (ident == C_CPP_HASHNODE (__bool_keyword))
246         {
247           expand_bool_p = true;
248           return C_CPP_HASHNODE (__vector_keyword);
249         }
250       else if (ident)
251         rid_code = (enum rid)(ident->rid_code);
252     }
253
254   /* vector keyword followed by type identifier: vector unsigned,
255      vector long, ...
256      Types consisting of more than one identifier are not supported by
257      zvector e.g. long long, long double, unsigned long int.  */
258   if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
259       || rid_code == RID_SHORT || rid_code == RID_SIGNED
260       || rid_code == RID_INT || rid_code == RID_CHAR
261       || rid_code == RID_DOUBLE)
262     {
263       expand_this = C_CPP_HASHNODE (__vector_keyword);
264       /* If the next keyword is bool, it will need to be expanded as
265          well.  */
266       do
267         tok = cpp_peek_token (pfile, idx++);
268       while (tok->type == CPP_PADDING);
269       ident = s390_categorize_keyword (tok);
270
271       /* __vector long __bool a; */
272       if (ident == C_CPP_HASHNODE (__bool_keyword))
273         expand_bool_p = true;
274       else
275         {
276           /* Triggered with: __vector long long __bool a; */
277           do
278             tok = cpp_peek_token (pfile, idx++);
279           while (tok->type == CPP_PADDING);
280           ident = s390_categorize_keyword (tok);
281
282           if (ident == C_CPP_HASHNODE (__bool_keyword))
283             expand_bool_p = true;
284         }
285     }
286
287   return expand_this;
288 }
289
290 /* Define platform dependent macros.  */
291 void
292 s390_cpu_cpp_builtins (cpp_reader *pfile)
293 {
294   cpp_assert (pfile, "cpu=s390");
295   cpp_assert (pfile, "machine=s390");
296   cpp_define (pfile, "__s390__");
297   if (TARGET_ZARCH)
298     cpp_define (pfile, "__zarch__");
299   if (TARGET_64BIT)
300     cpp_define (pfile, "__s390x__");
301   if (TARGET_LONG_DOUBLE_128)
302     cpp_define (pfile, "__LONG_DOUBLE_128__");
303   if (TARGET_HTM)
304     cpp_define (pfile, "__HTM__");
305   if (TARGET_ZVECTOR)
306     {
307       cpp_define (pfile, "__VEC__=10301");
308       cpp_define (pfile, "__vector=__attribute__((vector_size(16)))");
309       cpp_define (pfile, "__bool=__attribute__((s390_vector_bool)) unsigned");
310
311       if (!flag_iso)
312         {
313           cpp_define (pfile, "__VECTOR_KEYWORD_SUPPORTED__");
314           cpp_define (pfile, "vector=vector");
315           cpp_define (pfile, "bool=bool");
316
317           __vector_keyword = get_identifier ("__vector");
318           C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
319
320           vector_keyword = get_identifier ("vector");
321           C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
322
323           __bool_keyword = get_identifier ("__bool");
324           C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
325
326           bool_keyword = get_identifier ("bool");
327           C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
328
329           _Bool_keyword = get_identifier ("_Bool");
330           C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
331
332           /* Enable context-sensitive macros.  */
333           cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
334         }
335     }
336 }
337
338 /* Expand builtins which can directly be mapped to tree expressions.
339    LOC - location information
340    FCODE - function code of the builtin
341    ARGLIST - value supposed to be passed as arguments
342    RETURN-TYPE - expected return type of the builtin */
343 static tree
344 s390_expand_overloaded_builtin (location_t loc,
345                                 unsigned fcode,
346                                 vec<tree, va_gc> *arglist,
347                                 tree return_type)
348 {
349   switch (fcode)
350     {
351     case S390_OVERLOADED_BUILTIN_s390_vec_step:
352       if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
353         {
354           error_at (loc, "Builtin vec_step can only be used on vector types.");
355           return error_mark_node;
356         }
357       return build_int_cst (NULL_TREE,
358                             TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
359     case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
360     case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
361       return build2 (MEM_REF, return_type,
362                      fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
363                      build_int_cst (TREE_TYPE ((*arglist)[1]), 0));
364     case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
365     case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
366       return build2 (MODIFY_EXPR, TREE_TYPE((*arglist)[0]),
367                      build1 (INDIRECT_REF, TREE_TYPE((*arglist)[0]),
368                              fold_build_pointer_plus ((*arglist)[2], (*arglist)[1])),
369                      (*arglist)[0]);
370     case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
371       return build_constructor_va (return_type, 2,
372                                    NULL_TREE, (*arglist)[0],
373                                    NULL_TREE, (*arglist)[1]);
374     default:
375       gcc_unreachable ();
376     }
377 }
378
379 /* invert result */
380 #define __VSTRING_FLAG_IN         8
381 /* result type */
382 #define __VSTRING_FLAG_RT         4
383 /* zero search */
384 #define __VSTRING_FLAG_ZS         2
385 /* set condition code */
386 #define __VSTRING_FLAG_CS         1
387
388 /* Return the flags value to be used for string low-level builtins
389    when expanded from overloaded builtin OB_FCODE.  */
390 static unsigned int
391 s390_get_vstring_flags (int ob_fcode)
392 {
393   unsigned int flags = 0;
394
395   switch (ob_fcode)
396     {
397     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
398     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
399     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
400     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
401     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
402     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
403     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
404     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
405     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
406     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
407     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
408     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
409       flags |= __VSTRING_FLAG_IN;
410       break;
411     default:
412       break;
413     }
414   switch (ob_fcode)
415     {
416
417     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
418     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
419     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
420     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
421     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
422     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
423     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
424     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
425       flags |= __VSTRING_FLAG_RT;
426       break;
427     default:
428       break;
429     }
430   switch (ob_fcode)
431     {
432
433     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
434     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
435     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
436     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
437     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
438     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
439     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
440     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
441       flags |= __VSTRING_FLAG_ZS;
442       break;
443     default:
444       break;
445     }
446   switch (ob_fcode)
447     {
448     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
449     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
450     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
451     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
452     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
453     case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
454     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
455     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
456     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
457     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
458     case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
459     case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
460       flags |= __VSTRING_FLAG_CS;
461       break;
462     default:
463       break;
464     }
465   return flags;
466 }
467 #undef __VSTRING_FLAG_IN
468 #undef __VSTRING_FLAG_RT
469 #undef __VSTRING_FLAG_ZS
470 #undef __VSTRING_FLAG_CS
471
472 /* For several overloaded builtins the argument lists do not match
473    exactly the signature of a low-level builtin.  This function
474    adjusts the argument list ARGLIST for the overloaded builtin
475    OB_FCODE to the signature of the low-level builtin given by
476    DECL.  */
477 static void
478 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
479                              vec<tree, va_gc> **arglist)
480 {
481   tree arg_chain;
482   int src_arg_index, dest_arg_index;
483   vec<tree, va_gc> *folded_args = NULL;
484
485   /* We at most add one more operand to the list.  */
486   vec_alloc (folded_args, (*arglist)->allocated () + 1);
487   for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
488          src_arg_index = 0, dest_arg_index = 0;
489        !VOID_TYPE_P (TREE_VALUE (arg_chain));
490        arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
491     {
492       bool arg_assigned_p = false;
493       switch (ob_fcode)
494         {
495           /* For all these the low level builtin needs an additional flags parameter.  */
496         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
497         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
498         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
499         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
500         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
501         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
502         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
503         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
504         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
505         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
506         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
507         case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
508           if (dest_arg_index == 2)
509             {
510               folded_args->quick_push (build_int_cst (integer_type_node,
511                                        s390_get_vstring_flags (ob_fcode)));
512               arg_assigned_p = true;
513             }
514           break;
515         case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
516         case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
517         case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
518         case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
519         case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
520         case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
521         case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
522         case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
523         case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
524         case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
525         case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
526         case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
527           if (dest_arg_index == 3)
528             {
529               folded_args->quick_push (build_int_cst (integer_type_node,
530                                        s390_get_vstring_flags (ob_fcode)));
531               arg_assigned_p = true;
532             }
533           break;
534         case S390_OVERLOADED_BUILTIN_s390_vec_sel:
535         case S390_OVERLOADED_BUILTIN_s390_vec_insert:
536         case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
537           /* Swap the first to arguments. It is better to do it here
538              instead of the header file to avoid operand checking
539              throwing error messages for a weird operand index.  */
540           if (dest_arg_index < 2)
541             {
542               folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
543                                          (**arglist)[1 - dest_arg_index]));
544               src_arg_index++;
545               arg_assigned_p = true;
546             }
547           break;
548         case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
549           if (dest_arg_index == 1 || dest_arg_index == 2)
550             {
551               folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
552                                          (**arglist)[3 - dest_arg_index]));
553               src_arg_index++;
554               arg_assigned_p = true;
555             }
556           break;
557
558         case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
559           {
560             int code;
561
562             if (dest_arg_index == 1)
563               {
564                 switch (tree_to_uhwi ((**arglist)[src_arg_index]))
565                   {
566                   case 64: code = 0; break;
567                   case 128: code = 1; break;
568                   case 256: code = 2; break;
569                   case 512: code = 3; break;
570                   case 1024: code = 4; break;
571                   case 2048: code = 5; break;
572                   case 4096: code = 6; break;
573                   default:
574                     error ("valid values for builtin %qF argument %d are 64, "
575                            "128, 256, 512, 1024, 2048, and 4096", decl,
576                            src_arg_index + 1);
577                     return;
578                   }
579                 folded_args->quick_push (build_int_cst (integer_type_node,
580                                                         code));
581                 src_arg_index++;
582                 arg_assigned_p = true;
583               }
584           }
585           break;
586         case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
587           /* Duplicate the first src arg.  */
588           if (dest_arg_index == 0)
589             {
590               folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
591                                            (**arglist)[src_arg_index]));
592               arg_assigned_p = true;
593             }
594           break;
595         default:
596           break;
597         }
598       if (!arg_assigned_p)
599         {
600           folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
601                                                  (**arglist)[src_arg_index]));
602           src_arg_index++;
603         }
604     }
605   *arglist = folded_args;
606 }
607
608 /* Check whether the arguments in ARGLIST match the function type
609    DEF_TYPE. Return the number of argument types which required
610    conversion/promotion in order to make it match.
611    0 stands for a perfect match - all operand types match without changes
612    INT_MAX stands for a mismatch.  */
613 static int
614 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
615                           vec<tree, va_gc> *arglist)
616 {
617   unsigned int i;
618   int match_type = 0;
619
620   for (i = 0; i < vec_safe_length (arglist); i++)
621     {
622       tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
623       tree in_arg = (*arglist)[i];
624       tree in_type = TREE_TYPE (in_arg);
625
626       if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
627         {
628           /* Vector types have to match precisely.  */
629           if (b_arg_type != in_type
630               && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
631             goto mismatch;
632         }
633
634       if (lang_hooks.types_compatible_p (in_type, b_arg_type))
635         continue;
636
637       if (lang_hooks.types_compatible_p (
638             lang_hooks.types.type_promotes_to (in_type),
639             lang_hooks.types.type_promotes_to (b_arg_type)))
640         {
641           match_type++;
642           continue;
643         }
644
645       /* In this stage the C++ frontend would go ahead trying to find
646          implicit conversion chains for the argument to match the
647          target type.  We will mimic this here only for our limited
648          subset of argument types.  */
649       if (TREE_CODE (b_arg_type) == INTEGER_TYPE
650           && TREE_CODE (in_type) == INTEGER_TYPE)
651         {
652           match_type++;
653           continue;
654         }
655
656       /* If the incoming pointer argument has more qualifiers than the
657          argument type it can still be an imperfect match.  */
658       if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
659           && !(TYPE_QUALS (TREE_TYPE (in_type))
660                & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
661           && (TYPE_QUALS (TREE_TYPE (b_arg_type))
662               & ~TYPE_QUALS (TREE_TYPE (in_type))))
663         {
664           tree qual_in_type =
665             build_qualified_type (TREE_TYPE (in_type),
666                                   TYPE_QUALS (TREE_TYPE (b_arg_type)));
667
668           if (lang_hooks.types_compatible_p (qual_in_type,
669                                              TREE_TYPE (b_arg_type)))
670             {
671               match_type++;
672               continue;
673             }
674         }
675
676     mismatch:
677       if (TARGET_DEBUG_ARG)
678         fprintf (stderr, " mismatch in operand: %d\n", i + 1);
679       return INT_MAX;
680     }
681
682   return match_type;
683 }
684
685 /* Return the number of elements in the vector arguments of FNDECL in
686    case all it matches for all vector arguments, -1 otherwise.  */
687 static int
688 s390_vec_n_elem (tree fndecl)
689 {
690   tree b_arg_chain;
691   int n_elem = -1;
692
693   if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) == VECTOR_TYPE)
694     n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
695
696   for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
697        !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
698        b_arg_chain = TREE_CHAIN (b_arg_chain))
699     {
700       int tmp_n_elem;
701       if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
702         continue;
703       tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
704       if (n_elem != -1 && n_elem != tmp_n_elem)
705         return -1;
706       n_elem = tmp_n_elem;
707     }
708   return n_elem;
709 }
710
711
712 /* Return a tree expression for a call to the overloaded builtin
713    function OB_FNDECL at LOC with arguments PASSED_ARGLIST.  */
714 tree
715 s390_resolve_overloaded_builtin (location_t loc,
716                                  tree ob_fndecl,
717                                  void *passed_arglist)
718 {
719   vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
720   unsigned int in_args_num = vec_safe_length (arglist);
721   unsigned int ob_args_num = 0;
722   unsigned int ob_fcode = DECL_FUNCTION_CODE (ob_fndecl);
723   enum s390_overloaded_builtin_vars bindex;
724   unsigned int i;
725   int last_match_type = INT_MAX;
726   int last_match_index = -1;
727   unsigned int all_op_flags;
728   int num_matches = 0;
729   tree target_builtin_decl, b_arg_chain, return_type;
730   enum s390_builtin_ov_type_index last_match_fntype_index;
731
732   if (TARGET_DEBUG_ARG)
733     fprintf (stderr,
734       "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
735       (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
736      ob_fcode < S390_BUILTIN_MAX ? "not" : "");
737
738   /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins.  */
739   if (ob_fcode < S390_BUILTIN_MAX)
740     {
741       if (bflags_for_builtin(ob_fcode) & B_INT)
742         {
743           error_at (loc,
744                     "Builtin %qF is for GCC internal use only.",
745                     ob_fndecl);
746           return error_mark_node;
747         }
748       return NULL_TREE;
749     }
750
751   ob_fcode -= S390_BUILTIN_MAX;
752
753   for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
754        !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
755        b_arg_chain = TREE_CHAIN (b_arg_chain))
756     ob_args_num++;
757
758   if (ob_args_num != in_args_num)
759     {
760       error_at (loc,
761                 "Mismatch in number of arguments for builtin %qF. "
762                 "Expected: %d got %d", ob_fndecl,
763                 ob_args_num, in_args_num);
764       return error_mark_node;
765     }
766
767   for (i = 0; i < in_args_num; i++)
768     if ((*arglist)[i] == error_mark_node)
769       return error_mark_node;
770
771   /* Overloaded builtins without any variants are directly expanded here.  */
772   if (desc_start_for_overloaded_builtin[ob_fcode] ==
773       S390_OVERLOADED_BUILTIN_VAR_MAX)
774     return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
775
776   for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
777        bindex <= desc_end_for_overloaded_builtin[ob_fcode];
778        bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
779   {
780     int match_type;
781     enum s390_builtin_ov_type_index type_index =
782       type_for_overloaded_builtin_var[bindex];
783
784     if (TARGET_DEBUG_ARG)
785       fprintf (stderr, "checking variant number: %d", (int)bindex);
786
787     match_type = s390_fn_types_compatible (type_index, arglist);
788
789     if (match_type == INT_MAX)
790       continue;
791
792     if (TARGET_DEBUG_ARG)
793       fprintf (stderr,
794                " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
795                match_type);
796
797     if (match_type < last_match_type)
798       {
799         num_matches = 1;
800         last_match_type = match_type;
801         last_match_fntype_index = type_index;
802         last_match_index = bindex;
803       }
804     else if (match_type == last_match_type)
805       num_matches++;
806   }
807
808   if (last_match_type == INT_MAX)
809     {
810       error_at (loc, "invalid parameter combination for intrinsic");
811       return error_mark_node;
812     }
813   else if (num_matches > 1)
814     {
815       error_at (loc, "ambiguous overload for intrinsic: %s\n",
816              IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
817       return error_mark_node;
818     }
819
820   if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
821     target_builtin_decl = ob_fndecl;
822   else
823     target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
824
825   all_op_flags = opflags_overloaded_builtin_var[last_match_index];
826   return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
827
828   /* Check for the operand flags in the overloaded builtin variant.  */
829   for (i = 0; i < ob_args_num; i++)
830     {
831       unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
832       tree arg = (*arglist)[i];
833       tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
834
835       all_op_flags = all_op_flags >> O_SHIFT;
836
837       if (op_flags == O_ELEM)
838         {
839           int n_elem = s390_vec_n_elem (target_builtin_decl);
840           gcc_assert (n_elem > 0);
841           gcc_assert (type == integer_type_node);
842           (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
843                                   fold_convert (integer_type_node, arg),
844                                   build_int_cst (NULL_TREE, n_elem - 1));
845         }
846
847       if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
848         continue;
849
850       if ((TYPE_UNSIGNED (type)
851            && !int_fits_type_p (arg, c_common_unsigned_type (type)))
852           || (!TYPE_UNSIGNED (type)
853               && !int_fits_type_p (arg, c_common_signed_type (type))))
854         {
855           error("constant argument %d for builtin %qF is out "
856                 "of range for target type",
857                 i + 1, target_builtin_decl);
858           return error_mark_node;
859         }
860
861       if (TREE_CODE (arg) == INTEGER_CST
862           && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
863         return error_mark_node;
864     }
865
866   /* Handle builtins we expand directly - without mapping it to a low
867      level builtin.  */
868   if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
869     return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
870
871   s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
872
873   if (VOID_TYPE_P (return_type))
874     return build_function_call_vec (loc, vNULL, target_builtin_decl,
875                                     arglist, NULL);
876   else
877     return fully_fold_convert (return_type,
878                                build_function_call_vec (loc, vNULL, target_builtin_decl,
879                                                         arglist, NULL));
880 }
881
882 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h.  */
883 void
884 s390_register_target_pragmas (void)
885 {
886   targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
887 }