1 /* Language specific subroutines used for code generation on IBM S/390
3 Copyright (C) 2015 Free Software Foundation, Inc.
5 Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
7 This file is part of GCC.
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)
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.
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/>.
23 Based on gcc/config/rs6000/rs6000-c.c.
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. */
32 #include "coretypes.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"
44 #include "langhooks.h"
45 #include "tree-pretty-print.h"
48 #include "s390-builtins.h"
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
;
57 /* Generate an array holding all the descriptions of variants of
58 overloaded builtins defined with OB_DEF_VAR in
60 static enum s390_builtin_ov_type_index
61 type_for_overloaded_builtin_var
[S390_OVERLOADED_BUILTIN_VAR_MAX
+ 1] =
68 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, FNTYPE) FNTYPE,
69 #include "s390-builtins.def"
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] =
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
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] =
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
108 static enum s390_builtin_type_index
109 s390_builtin_ov_types
[BT_OV_MAX
][MAX_OV_OPERANDS
] =
112 #undef DEF_POINTER_TYPE
113 #undef DEF_DISTINCT_TYPE
114 #undef DEF_VECTOR_TYPE
115 #undef DEF_OPAQUE_VECTOR_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"
128 static const enum s390_builtins
129 bt_for_overloaded_builtin_var
[S390_OVERLOADED_BUILTIN_VAR_MAX
] = {
135 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
137 #include "s390-builtins.def"
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). */
144 fully_fold_convert (tree type
, tree expr
)
146 tree result
= fold_convert (type
, expr
);
147 bool maybe_const
= true;
149 if (!c_dialect_cxx ())
150 result
= c_fully_fold (result
, false, &maybe_const
);
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
)
160 if (tok
->type
== CPP_NAME
)
162 cpp_hashnode
*ident
= tok
->val
.node
.node
;
164 if (ident
== C_CPP_HASHNODE (vector_keyword
))
165 return C_CPP_HASHNODE (__vector_keyword
);
167 if (ident
== C_CPP_HASHNODE (bool_keyword
))
168 return C_CPP_HASHNODE (__bool_keyword
);
170 if (ident
== C_CPP_HASHNODE (_Bool_keyword
))
171 return C_CPP_HASHNODE (__bool_keyword
);
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. */
183 static cpp_hashnode
*
184 s390_macro_to_expand (cpp_reader
*pfile
, const cpp_token
*tok
)
186 cpp_hashnode
*expand_this
= tok
->val
.node
.node
;
188 static bool expand_bool_p
= false;
192 /* The vector keyword is only expanded if the machine actually
193 provides hardware support. */
197 ident
= s390_categorize_keyword (tok
);
199 /* Triggered when we picked a different variant in
200 s390_categorize_keyword. */
201 if (ident
!= expand_this
)
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
))
208 expand_bool_p
= false;
212 if (ident
!= C_CPP_HASHNODE (__vector_keyword
))
216 tok
= cpp_peek_token (pfile
, idx
++);
217 while (tok
->type
== CPP_PADDING
);
218 ident
= s390_categorize_keyword (tok
);
223 /* vector bool - remember to expand the next bool. */
224 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
226 expand_bool_p
= true;
227 return C_CPP_HASHNODE (__vector_keyword
);
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
))
236 rid_code
= (enum rid
)(ident
->rid_code
);
238 if (ident
->type
== NT_MACRO
)
240 /* Now actually fetch the tokens we "peeked" before and do a
241 lookahead for the next. */
243 (void) cpp_get_token (pfile
);
246 tok
= cpp_peek_token (pfile
, idx
++);
247 while (tok
->type
== CPP_PADDING
);
248 ident
= s390_categorize_keyword (tok
);
250 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
252 expand_bool_p
= true;
253 return C_CPP_HASHNODE (__vector_keyword
);
256 rid_code
= (enum rid
)(ident
->rid_code
);
259 /* vector keyword followed by type identifier: vector unsigned,
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
)
268 expand_this
= C_CPP_HASHNODE (__vector_keyword
);
269 /* If the next keyword is bool, it will need to be expanded as
272 tok
= cpp_peek_token (pfile
, idx
++);
273 while (tok
->type
== CPP_PADDING
);
274 ident
= s390_categorize_keyword (tok
);
276 /* __vector long __bool a; */
277 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
278 expand_bool_p
= true;
281 /* Triggered with: __vector long long __bool a; */
283 tok
= cpp_peek_token (pfile
, idx
++);
284 while (tok
->type
== CPP_PADDING
);
285 ident
= s390_categorize_keyword (tok
);
287 if (ident
== C_CPP_HASHNODE (__bool_keyword
))
288 expand_bool_p
= true;
295 /* Define platform dependent macros. */
297 s390_cpu_cpp_builtins (cpp_reader
*pfile
)
299 cpp_assert (pfile
, "cpu=s390");
300 cpp_assert (pfile
, "machine=s390");
301 cpp_define (pfile
, "__s390__");
303 cpp_define (pfile
, "__zarch__");
305 cpp_define (pfile
, "__s390x__");
306 if (TARGET_LONG_DOUBLE_128
)
307 cpp_define (pfile
, "__LONG_DOUBLE_128__");
309 cpp_define (pfile
, "__HTM__");
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");
318 cpp_define (pfile
, "__VECTOR_KEYWORD_SUPPORTED__");
319 cpp_define (pfile
, "vector=vector");
320 cpp_define (pfile
, "bool=bool");
322 __vector_keyword
= get_identifier ("__vector");
323 C_CPP_HASHNODE (__vector_keyword
)->flags
|= NODE_CONDITIONAL
;
325 vector_keyword
= get_identifier ("vector");
326 C_CPP_HASHNODE (vector_keyword
)->flags
|= NODE_CONDITIONAL
;
328 __bool_keyword
= get_identifier ("__bool");
329 C_CPP_HASHNODE (__bool_keyword
)->flags
|= NODE_CONDITIONAL
;
331 bool_keyword
= get_identifier ("bool");
332 C_CPP_HASHNODE (bool_keyword
)->flags
|= NODE_CONDITIONAL
;
334 _Bool_keyword
= get_identifier ("_Bool");
335 C_CPP_HASHNODE (_Bool_keyword
)->flags
|= NODE_CONDITIONAL
;
337 /* Enable context-sensitive macros. */
338 cpp_get_callbacks (pfile
)->macro_to_expand
= s390_macro_to_expand
;
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 */
349 s390_expand_overloaded_builtin (location_t loc
,
351 vec
<tree
, va_gc
> *arglist
,
356 case S390_OVERLOADED_BUILTIN_s390_vec_step
:
357 if (TREE_CODE (TREE_TYPE ((*arglist
)[0])) != VECTOR_TYPE
)
359 error_at (loc
, "Builtin vec_step can only be used on vector types.");
360 return error_mark_node
;
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])),
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]);
385 #define __VSTRING_FLAG_IN 8
387 #define __VSTRING_FLAG_RT 4
389 #define __VSTRING_FLAG_ZS 2
390 /* set condition code */
391 #define __VSTRING_FLAG_CS 1
393 /* Return the flags value to be used for string low-level builtins
394 when expanded from overloaded builtin OB_FCODE. */
396 s390_get_vstring_flags (int ob_fcode
)
398 unsigned int flags
= 0;
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
;
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
;
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
;
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
;
480 #undef __VSTRING_FLAG_IN
481 #undef __VSTRING_FLAG_RT
482 #undef __VSTRING_FLAG_ZS
483 #undef __VSTRING_FLAG_CS
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
491 s390_adjust_builtin_arglist (unsigned int ob_fcode
, tree decl
,
492 vec
<tree
, va_gc
> **arglist
)
495 int src_arg_index
, dest_arg_index
;
496 vec
<tree
, va_gc
> *folded_args
= NULL
;
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
++)
505 bool arg_assigned_p
= false;
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)
523 folded_args
->quick_push (build_int_cst (integer_type_node
,
524 s390_get_vstring_flags (ob_fcode
)));
525 arg_assigned_p
= true;
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)
542 folded_args
->quick_push (build_int_cst (integer_type_node
,
543 s390_get_vstring_flags (ob_fcode
)));
544 arg_assigned_p
= true;
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)
555 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
556 (**arglist
)[1 - dest_arg_index
]));
558 arg_assigned_p
= true;
561 case S390_OVERLOADED_BUILTIN_s390_vec_store_len
:
562 if (dest_arg_index
== 1 || dest_arg_index
== 2)
564 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
565 (**arglist
)[3 - dest_arg_index
]));
567 arg_assigned_p
= true;
571 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry
:
575 if (dest_arg_index
== 1)
577 switch (tree_to_uhwi ((**arglist
)[src_arg_index
]))
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;
587 error ("valid values for builtin %qF argument %d are 64, "
588 "128, 256, 512, 1024, 2048, and 4096", decl
,
592 folded_args
->quick_push (build_int_cst (integer_type_node
,
595 arg_assigned_p
= true;
599 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask
:
600 /* Duplicate the first src arg. */
601 if (dest_arg_index
== 0)
603 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
604 (**arglist
)[src_arg_index
]));
605 arg_assigned_p
= true;
613 folded_args
->quick_push (fully_fold_convert (TREE_VALUE (arg_chain
),
614 (**arglist
)[src_arg_index
]));
618 *arglist
= folded_args
;
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. */
627 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex
,
628 vec
<tree
, va_gc
> *arglist
)
633 for (i
= 0; i
< vec_safe_length (arglist
); i
++)
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
);
639 if (TREE_CODE (b_arg_type
) == VECTOR_TYPE
)
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
))
647 if (lang_hooks
.types_compatible_p (in_type
, b_arg_type
))
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
)))
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
)
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
))))
678 build_qualified_type (TREE_TYPE (in_type
),
679 TYPE_QUALS (TREE_TYPE (b_arg_type
)));
681 if (lang_hooks
.types_compatible_p (qual_in_type
,
682 TREE_TYPE (b_arg_type
)))
690 if (TARGET_DEBUG_ARG
)
691 fprintf (stderr
, " mismatch in operand: %d\n", i
+ 1);
698 /* Return the number of elements in the vector arguments of FNDECL in
699 case all it matches for all vector arguments, -1 otherwise. */
701 s390_vec_n_elem (tree fndecl
)
706 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl
))) == VECTOR_TYPE
)
707 n_elem
= TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl
))));
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
))
714 if (TREE_CODE (TREE_VALUE (b_arg_chain
)) != VECTOR_TYPE
)
716 tmp_n_elem
= TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain
));
717 if (n_elem
!= -1 && n_elem
!= tmp_n_elem
)
725 /* Return a tree expression for a call to the overloaded builtin
726 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
728 s390_resolve_overloaded_builtin (location_t loc
,
730 void *passed_arglist
)
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
;
738 int last_match_type
= INT_MAX
;
739 int last_match_index
= -1;
740 unsigned int all_op_flags
;
742 tree target_builtin_decl
, b_arg_chain
, return_type
;
743 enum s390_builtin_ov_type_index last_match_fntype_index
;
745 if (TARGET_DEBUG_ARG
)
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" : "");
751 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
752 if (ob_fcode
< S390_BUILTIN_MAX
)
754 if (bflags_for_builtin(ob_fcode
) & B_INT
)
757 "Builtin %qF is for GCC internal use only.",
759 return error_mark_node
;
764 ob_fcode
-= S390_BUILTIN_MAX
;
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
))
771 if (ob_args_num
!= in_args_num
)
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
;
780 for (i
= 0; i
< in_args_num
; i
++)
781 if ((*arglist
)[i
] == error_mark_node
)
782 return error_mark_node
;
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
);
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))
794 enum s390_builtin_ov_type_index type_index
=
795 type_for_overloaded_builtin_var
[bindex
];
797 if (TARGET_DEBUG_ARG
)
798 fprintf (stderr
, "checking variant number: %d", (int)bindex
);
800 match_type
= s390_fn_types_compatible (type_index
, arglist
);
802 if (match_type
== INT_MAX
)
805 if (TARGET_DEBUG_ARG
)
807 " %s match score: %d\n", match_type
== 0 ? "perfect" : "imperfect",
810 if (match_type
< last_match_type
)
813 last_match_type
= match_type
;
814 last_match_fntype_index
= type_index
;
815 last_match_index
= bindex
;
817 else if (match_type
== last_match_type
)
821 if (last_match_type
== INT_MAX
)
823 error_at (loc
, "invalid parameter combination for intrinsic");
824 return error_mark_node
;
826 else if (num_matches
> 1)
828 error_at (loc
, "ambiguous overload for intrinsic: %s\n",
829 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl
)));
830 return error_mark_node
;
833 if (bt_for_overloaded_builtin_var
[last_match_index
] == S390_BUILTIN_MAX
)
834 target_builtin_decl
= ob_fndecl
;
836 target_builtin_decl
= s390_builtin_decls
[bt_for_overloaded_builtin_var
[last_match_index
]];
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]];
841 /* Check for the operand flags in the overloaded builtin variant. */
842 for (i
= 0; i
< ob_args_num
; i
++)
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]];
848 all_op_flags
= all_op_flags
>> O_SHIFT
;
850 if (op_flags
== O_ELEM
)
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));
860 if (TREE_CODE (arg
) != INTEGER_CST
|| !O_IMM_P (op_flags
))
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
))))
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
;
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
;
879 /* Handle builtins we expand directly - without mapping it to a low
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
);
884 s390_adjust_builtin_arglist (ob_fcode
, target_builtin_decl
, &arglist
);
886 if (VOID_TYPE_P (return_type
))
887 return build_function_call_vec (loc
, vNULL
, target_builtin_decl
,
890 return fully_fold_convert (return_type
,
891 build_function_call_vec (loc
, vNULL
, target_builtin_decl
,
895 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
897 s390_register_target_pragmas (void)
899 targetm
.resolve_overloaded_builtin
= s390_resolve_overloaded_builtin
;