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