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