]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/s390/s390-c.c
Update copyright years.
[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-2020 Free Software Foundation, Inc.
4
5 Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>.
22
23 Based on gcc/config/rs6000/rs6000-c.c.
24
25 In GCC terms this file belongs to the frontend. It will be
26 compiled with -DIN_GCC_FRONTEND. With that rtl.h cannot be
27 included anymore - a mechanism supposed to avoid adding frontend -
28 backend dependencies. */
29
30 #define IN_TARGET_CODE 1
31
32 #include "config.h"
33 #include "system.h"
34 #include "coretypes.h"
35 #include "target.h"
36 #include "tree.h"
37 #include "c-family/c-common.h"
38 #include "c/c-tree.h"
39 #include "memmodel.h"
40 #include "tm_p.h"
41 #include "stringpool.h"
42 #include "c-family/c-pragma.h"
43 #include "langhooks.h"
44 #include "tree-pretty-print.h"
45
46 #include "s390-builtins.h"
47
48 static GTY(()) tree __vector_keyword;
49 static GTY(()) tree vector_keyword;
50 static GTY(()) tree __bool_keyword;
51 static GTY(()) tree bool_keyword;
52 static GTY(()) tree _Bool_keyword;
53
54
55 /* Generate an array holding all the descriptions of variants of
56 overloaded builtins defined with OB_DEF_VAR in
57 s390-builtins.def. */
58 static enum s390_builtin_ov_type_index
59 type_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX + 1] =
60 {
61 #undef B_DEF
62 #undef OB_DEF
63 #undef OB_DEF_VAR
64 #define B_DEF(...)
65 #define OB_DEF(...)
66 #define OB_DEF_VAR(NAME, PATTERN, FLAGS, OPFLAGS, FNTYPE) FNTYPE,
67 #include "s390-builtins.def"
68 BT_OV_MAX
69 };
70
71
72 /* Generate an array indexed by an overloaded builtin index returning
73 the first index in desc_for_overloaded_builtin_var where the
74 variants for the builtin can be found. */
75 static enum s390_overloaded_builtin_vars
76 desc_start_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
77 {
78 #undef B_DEF
79 #undef OB_DEF
80 #undef OB_DEF_VAR
81 #define B_DEF(...)
82 #define OB_DEF(NAME, FIRST_VAR_NAME,...) \
83 S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
84 #define OB_DEF_VAR(...)
85 #include "s390-builtins.def"
86 S390_OVERLOADED_BUILTIN_VAR_MAX
87 };
88
89 /* Generate an array indexed by an overloaded builtin index returning
90 the last index in desc_for_overloaded_builtin_var where the
91 variants for the builtin can be found. */
92 static enum s390_overloaded_builtin_vars
93 desc_end_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
94 {
95 #undef B_DEF
96 #undef OB_DEF
97 #undef OB_DEF_VAR
98 #define B_DEF(...)
99 #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...) \
100 S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
101 #define OB_DEF_VAR(...)
102 #include "s390-builtins.def"
103 S390_OVERLOADED_BUILTIN_VAR_MAX
104 };
105
106 static enum s390_builtin_type_index
107 s390_builtin_ov_types[BT_OV_MAX][MAX_OV_OPERANDS] =
108 {
109 #undef DEF_TYPE
110 #undef DEF_POINTER_TYPE
111 #undef DEF_DISTINCT_TYPE
112 #undef DEF_VECTOR_TYPE
113 #undef DEF_OPAQUE_VECTOR_TYPE
114 #undef DEF_FN_TYPE
115 #undef DEF_OV_TYPE
116 #define DEF_TYPE(...)
117 #define DEF_POINTER_TYPE(...)
118 #define DEF_DISTINCT_TYPE(...)
119 #define DEF_VECTOR_TYPE(...)
120 #define DEF_OPAQUE_VECTOR_TYPE(...)
121 #define DEF_FN_TYPE(...)
122 #define DEF_OV_TYPE(INDEX, args...) { args },
123 #include "s390-builtin-types.def"
124 };
125
126 static const enum s390_builtins
127 bt_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX] = {
128 #undef B_DEF
129 #undef OB_DEF
130 #undef OB_DEF_VAR
131 #define B_DEF(...)
132 #define OB_DEF(...)
133 #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
134
135 #include "s390-builtins.def"
136 };
137
138 /* In addition to calling fold_convert for EXPR of type TYPE, also
139 call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
140 hiding there (PR47197). */
141 tree
142 fully_fold_convert (tree type, tree expr)
143 {
144 tree result = fold_convert (type, expr);
145 bool maybe_const = true;
146
147 if (!c_dialect_cxx ())
148 result = c_fully_fold (result, false, &maybe_const);
149
150 return result;
151 }
152
153 /* Unify the different variants to the same nodes in order to keep the
154 code working with it simple. */
155 static cpp_hashnode *
156 s390_categorize_keyword (const cpp_token *tok)
157 {
158 if (tok->type == CPP_NAME)
159 {
160 cpp_hashnode *ident = tok->val.node.node;
161
162 if (ident == C_CPP_HASHNODE (vector_keyword))
163 return C_CPP_HASHNODE (__vector_keyword);
164
165 if (ident == C_CPP_HASHNODE (bool_keyword))
166 return C_CPP_HASHNODE (__bool_keyword);
167
168 if (ident == C_CPP_HASHNODE (_Bool_keyword))
169 return C_CPP_HASHNODE (__bool_keyword);
170 return ident;
171 }
172
173 return 0;
174 }
175
176
177 /* Called to decide whether a conditional macro should be expanded.
178 Since we have exactly one such macro (i.e, 'vector'), we do not
179 need to examine the 'tok' parameter. */
180
181 static cpp_hashnode *
182 s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
183 {
184 cpp_hashnode *expand_this = tok->val.node.node;
185 cpp_hashnode *ident;
186 static bool expand_bool_p = false;
187 int idx = 0;
188 enum rid rid_code;
189
190 /* The vector keyword is only expanded if the machine actually
191 provides hardware support. */
192 if (!TARGET_ZVECTOR)
193 return NULL;
194
195 ident = s390_categorize_keyword (tok);
196
197 /* Triggered when we picked a different variant in
198 s390_categorize_keyword. */
199 if (ident != expand_this)
200 expand_this = NULL;
201
202 /* The vector keyword has been found already and we remembered to
203 expand the next bool. */
204 if (expand_bool_p && ident == C_CPP_HASHNODE (__bool_keyword))
205 {
206 expand_bool_p = false;
207 return ident;
208 }
209
210 if (ident != C_CPP_HASHNODE (__vector_keyword))
211 return expand_this;
212
213 do
214 tok = cpp_peek_token (pfile, idx++);
215 while (tok->type == CPP_PADDING);
216 ident = s390_categorize_keyword (tok);
217
218 if (!ident)
219 return expand_this;
220
221 /* vector bool - remember to expand the next bool. */
222 if (ident == C_CPP_HASHNODE (__bool_keyword))
223 {
224 expand_bool_p = true;
225 return C_CPP_HASHNODE (__vector_keyword);
226 }
227
228 /* The boost libraries have code with Iterator::vector vector in it.
229 If we allow the normal handling, this module will be called
230 recursively, and the vector will be skipped.; */
231 if (ident == C_CPP_HASHNODE (__vector_keyword))
232 return expand_this;
233
234 rid_code = (enum rid)(ident->rid_code);
235
236 if (cpp_macro_p (ident))
237 {
238 /* Now actually fetch the tokens we "peeked" before and do a
239 lookahead for the next. */
240 do
241 (void) cpp_get_token (pfile);
242 while (--idx > 0);
243 do
244 tok = cpp_peek_token (pfile, idx++);
245 while (tok->type == CPP_PADDING);
246 ident = s390_categorize_keyword (tok);
247
248 if (ident == C_CPP_HASHNODE (__bool_keyword))
249 {
250 expand_bool_p = true;
251 return C_CPP_HASHNODE (__vector_keyword);
252 }
253 else if (ident)
254 rid_code = (enum rid)(ident->rid_code);
255 }
256
257 /* vector keyword followed by type identifier: vector unsigned,
258 vector long, ...
259 Types consisting of more than one identifier are not supported by
260 zvector e.g. long long, long double, unsigned long int. */
261 if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
262 || rid_code == RID_SHORT || rid_code == RID_SIGNED
263 || rid_code == RID_INT || rid_code == RID_CHAR
264 || (rid_code == RID_FLOAT && TARGET_VXE)
265 || rid_code == RID_DOUBLE)
266 {
267 expand_this = C_CPP_HASHNODE (__vector_keyword);
268 /* If the next keyword is bool, it will need to be expanded as
269 well. */
270 do
271 tok = cpp_peek_token (pfile, idx++);
272 while (tok->type == CPP_PADDING);
273 ident = s390_categorize_keyword (tok);
274
275 /* __vector long __bool a; */
276 if (ident == C_CPP_HASHNODE (__bool_keyword))
277 expand_bool_p = true;
278 else
279 {
280 /* Triggered with: __vector long long __bool a; */
281 do
282 tok = cpp_peek_token (pfile, idx++);
283 while (tok->type == CPP_PADDING);
284 ident = s390_categorize_keyword (tok);
285
286 if (ident == C_CPP_HASHNODE (__bool_keyword))
287 expand_bool_p = true;
288 }
289 }
290
291 return expand_this;
292 }
293
294 /* Helper function that defines or undefines macros. If SET is true, the macro
295 MACRO_DEF is defined. If SET is false, the macro MACRO_UNDEF is undefined.
296 Nothing is done if SET and WAS_SET have the same value. */
297 static void
298 s390_def_or_undef_macro (cpp_reader *pfile,
299 unsigned int mask,
300 const struct cl_target_option *old_opts,
301 const struct cl_target_option *new_opts,
302 const char *macro_def, const char *macro_undef)
303 {
304 bool was_set;
305 bool set;
306
307 was_set = (!old_opts) ? false : old_opts->x_target_flags & mask;
308 set = new_opts->x_target_flags & mask;
309 if (was_set == set)
310 return;
311 if (set)
312 cpp_define (pfile, macro_def);
313 else
314 cpp_undef (pfile, macro_undef);
315 }
316
317 /* Internal function to either define or undef the appropriate system
318 macros. */
319 static void
320 s390_cpu_cpp_builtins_internal (cpp_reader *pfile,
321 struct cl_target_option *opts,
322 const struct cl_target_option *old_opts)
323 {
324 s390_def_or_undef_macro (pfile, MASK_OPT_HTM, old_opts, opts,
325 "__HTM__", "__HTM__");
326 s390_def_or_undef_macro (pfile, MASK_OPT_VX, old_opts, opts,
327 "__VX__", "__VX__");
328 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
329 "__VEC__=10303", "__VEC__");
330 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
331 "__vector=__attribute__((vector_size(16)))",
332 "__vector__");
333 s390_def_or_undef_macro (pfile, MASK_ZVECTOR, old_opts, opts,
334 "__bool=__attribute__((s390_vector_bool)) unsigned",
335 "__bool");
336 {
337 char macro_def[64];
338 gcc_assert (s390_arch != PROCESSOR_NATIVE);
339 sprintf (macro_def, "__ARCH__=%d", processor_table[s390_arch].arch_level);
340 cpp_undef (pfile, "__ARCH__");
341 cpp_define (pfile, macro_def);
342 }
343
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)
354 {
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
376 /* Define platform dependent macros. */
377 void
378 s390_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__");
391 cl_target_option_save (&opts, &global_options);
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
400 static bool
401 s390_pragma_target_parse (tree args, tree pop_target)
402 {
403 tree prev_tree = build_target_option_node (&global_options);
404 tree cur_tree;
405
406 if (! args)
407 cur_tree = pop_target;
408 else
409 {
410 cur_tree = s390_valid_target_attribute_tree (args, &global_options,
411 &global_options_set, true);
412 if (!cur_tree || cur_tree == error_mark_node)
413 {
414 cl_target_option_restore (&global_options,
415 TREE_TARGET_OPTION (prev_tree));
416 return false;
417 }
418 }
419
420 target_option_current_node = cur_tree;
421 s390_activate_target_options (target_option_current_node);
422
423 {
424 struct cl_target_option *prev_opt;
425 struct cl_target_option *cur_opt;
426
427 /* Figure out the previous/current differences. */
428 prev_opt = TREE_TARGET_OPTION (prev_tree);
429 cur_opt = TREE_TARGET_OPTION (cur_tree);
430
431 /* For the definitions, ensure all newly defined macros are considered
432 as used for -Wunused-macros. There is no point warning about the
433 compiler predefined macros. */
434 cpp_options *cpp_opts = cpp_get_options (parse_in);
435 unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
436
437 cpp_opts->warn_unused_macros = 0;
438
439 /* Define all of the macros for new options that were just turned on. */
440 s390_cpu_cpp_builtins_internal (parse_in, cur_opt, prev_opt);
441
442 cpp_opts->warn_unused_macros = saved_warn_unused_macros;
443 }
444
445 return true;
446 }
447 #endif
448
449 /* Expand builtins which can directly be mapped to tree expressions.
450 LOC - location information
451 FCODE - function code of the builtin
452 ARGLIST - value supposed to be passed as arguments
453 RETURN-TYPE - expected return type of the builtin */
454 static tree
455 s390_expand_overloaded_builtin (location_t loc,
456 unsigned fcode,
457 vec<tree, va_gc> *arglist,
458 tree return_type)
459 {
460 switch (fcode)
461 {
462 case S390_OVERLOADED_BUILTIN_s390_vec_step:
463 if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
464 {
465 error_at (loc, "builtin vec_step can only be used on vector types.");
466 return error_mark_node;
467 }
468 return build_int_cst (NULL_TREE,
469 TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
470 case S390_OVERLOADED_BUILTIN_s390_vec_xl:
471 case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
472 case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
473 {
474 /* Build a vector type with the alignment of the source
475 location in order to enable correct alignment hints to be
476 generated for vl. */
477 tree mem_type = build_aligned_type (return_type,
478 TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[1]))));
479 return build2 (MEM_REF, mem_type,
480 fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
481 build_int_cst (TREE_TYPE ((*arglist)[1]), 0));
482 }
483 case S390_OVERLOADED_BUILTIN_s390_vec_xst:
484 case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
485 case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
486 {
487 /* Build a vector type with the alignment of the target
488 location in order to enable correct alignment hints to be
489 generated for vst. */
490 tree mem_type = build_aligned_type (TREE_TYPE((*arglist)[0]),
491 TYPE_ALIGN (TREE_TYPE (TREE_TYPE ((*arglist)[2]))));
492 return build2 (MODIFY_EXPR, mem_type,
493 build1 (INDIRECT_REF, mem_type,
494 fold_build_pointer_plus ((*arglist)[2], (*arglist)[1])),
495 (*arglist)[0]);
496 }
497 case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
498 return build_constructor_va (return_type, 2,
499 NULL_TREE, (*arglist)[0],
500 NULL_TREE, (*arglist)[1]);
501 default:
502 gcc_unreachable ();
503 }
504 }
505
506 /* invert result */
507 #define __VSTRING_FLAG_IN 8
508 /* result type */
509 #define __VSTRING_FLAG_RT 4
510 /* zero search */
511 #define __VSTRING_FLAG_ZS 2
512 /* set condition code */
513 #define __VSTRING_FLAG_CS 1
514
515 /* Return the flags value to be used for string low-level builtins
516 when expanded from overloaded builtin OB_FCODE. */
517 static unsigned int
518 s390_get_vstring_flags (int ob_fcode)
519 {
520 unsigned int flags = 0;
521
522 switch (ob_fcode)
523 {
524 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
525 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
526 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
527 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
528 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
529 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
530 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
531 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
532 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
533 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
534 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
535 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
536 flags |= __VSTRING_FLAG_IN;
537 break;
538 default:
539 break;
540 }
541 switch (ob_fcode)
542 {
543
544 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
545 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
546 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
547 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
548 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
549 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
550 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
551 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
552 flags |= __VSTRING_FLAG_RT;
553 break;
554 default:
555 break;
556 }
557 switch (ob_fcode)
558 {
559
560 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
561 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
562 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
563 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
564 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
565 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
566 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
567 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
568 flags |= __VSTRING_FLAG_ZS;
569 break;
570 default:
571 break;
572 }
573 switch (ob_fcode)
574 {
575 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
576 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
577 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
578 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
579 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
580 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
581 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
582 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
583 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
584 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
585 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
586 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
587 flags |= __VSTRING_FLAG_CS;
588 break;
589 default:
590 break;
591 }
592 return flags;
593 }
594 #undef __VSTRING_FLAG_IN
595 #undef __VSTRING_FLAG_RT
596 #undef __VSTRING_FLAG_ZS
597 #undef __VSTRING_FLAG_CS
598
599 /* For several overloaded builtins the argument lists do not match
600 exactly the signature of a low-level builtin. This function
601 adjusts the argument list ARGLIST for the overloaded builtin
602 OB_FCODE to the signature of the low-level builtin given by
603 DECL. */
604 static void
605 s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
606 vec<tree, va_gc> **arglist)
607 {
608 tree arg_chain;
609 int src_arg_index, dest_arg_index;
610 vec<tree, va_gc> *folded_args = NULL;
611
612 /* We at most add one more operand to the list. */
613 vec_alloc (folded_args, (*arglist)->allocated () + 1);
614 for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
615 src_arg_index = 0, dest_arg_index = 0;
616 !VOID_TYPE_P (TREE_VALUE (arg_chain));
617 arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
618 {
619 bool arg_assigned_p = false;
620 switch (ob_fcode)
621 {
622 /* For all these the low level builtin needs an additional flags parameter. */
623 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
624 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
625 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
626 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
627 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
628 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
629 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
630 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
631 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
632 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
633 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
634 case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
635 if (dest_arg_index == 2)
636 {
637 folded_args->quick_push (build_int_cst (integer_type_node,
638 s390_get_vstring_flags (ob_fcode)));
639 arg_assigned_p = true;
640 }
641 break;
642 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
643 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
644 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
645 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
646 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
647 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
648 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
649 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
650 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
651 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
652 case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
653 case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
654 if (dest_arg_index == 3)
655 {
656 folded_args->quick_push (build_int_cst (integer_type_node,
657 s390_get_vstring_flags (ob_fcode)));
658 arg_assigned_p = true;
659 }
660 break;
661 case S390_OVERLOADED_BUILTIN_s390_vec_sel:
662 case S390_OVERLOADED_BUILTIN_s390_vec_insert:
663 case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
664 /* Swap the first to arguments. It is better to do it here
665 instead of the header file to avoid operand checking
666 throwing error messages for a weird operand index. */
667 if (dest_arg_index < 2)
668 {
669 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
670 (**arglist)[1 - dest_arg_index]));
671 src_arg_index++;
672 arg_assigned_p = true;
673 }
674 break;
675 case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
676 if (dest_arg_index == 1 || dest_arg_index == 2)
677 {
678 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
679 (**arglist)[3 - dest_arg_index]));
680 src_arg_index++;
681 arg_assigned_p = true;
682 }
683 break;
684
685 case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
686 {
687 int code;
688 if (dest_arg_index == 1)
689 {
690 tree arg = (**arglist)[src_arg_index];
691
692 if (TREE_CODE (arg) != INTEGER_CST)
693 {
694 error ("constant value required for builtin %qF argument %d",
695 decl, src_arg_index + 1);
696 return;
697 }
698
699 switch (tree_to_uhwi (arg))
700 {
701 case 64: code = 0; break;
702 case 128: code = 1; break;
703 case 256: code = 2; break;
704 case 512: code = 3; break;
705 case 1024: code = 4; break;
706 case 2048: code = 5; break;
707 case 4096: code = 6; break;
708 default:
709 error ("valid values for builtin %qF argument %d are 64, "
710 "128, 256, 512, 1024, 2048, and 4096", decl,
711 src_arg_index + 1);
712 return;
713 }
714 folded_args->quick_push (build_int_cst (integer_type_node,
715 code));
716 src_arg_index++;
717 arg_assigned_p = true;
718 }
719 }
720 break;
721 case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
722 /* Duplicate the first src arg. */
723 if (dest_arg_index == 0)
724 {
725 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
726 (**arglist)[src_arg_index]));
727 arg_assigned_p = true;
728 }
729 break;
730 default:
731 break;
732 }
733 if (!arg_assigned_p)
734 {
735 folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
736 (**arglist)[src_arg_index]));
737 src_arg_index++;
738 }
739 }
740 *arglist = folded_args;
741 }
742
743 /* Check whether the arguments in ARGLIST match the function type
744 DEF_TYPE. Return the number of argument types which required
745 conversion/promotion in order to make it match.
746 0 stands for a perfect match - all operand types match without changes
747 INT_MAX stands for a mismatch. */
748 static int
749 s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
750 vec<tree, va_gc> *arglist)
751 {
752 unsigned int i;
753 int match_type = 0;
754
755 for (i = 0; i < vec_safe_length (arglist); i++)
756 {
757 tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
758 tree in_arg = (*arglist)[i];
759 tree in_type = TREE_TYPE (in_arg);
760
761 if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
762 {
763 /* Vector types have to match precisely. */
764 if (b_arg_type != in_type
765 && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
766 goto mismatch;
767 }
768
769 if (lang_hooks.types_compatible_p (in_type, b_arg_type))
770 continue;
771
772 if (lang_hooks.types_compatible_p (
773 lang_hooks.types.type_promotes_to (in_type),
774 lang_hooks.types.type_promotes_to (b_arg_type)))
775 {
776 match_type++;
777 continue;
778 }
779
780 /* In this stage the C++ frontend would go ahead trying to find
781 implicit conversion chains for the argument to match the
782 target type. We will mimic this here only for our limited
783 subset of argument types. */
784 if (TREE_CODE (b_arg_type) == INTEGER_TYPE
785 && TREE_CODE (in_type) == INTEGER_TYPE)
786 {
787 match_type++;
788 continue;
789 }
790
791 /* If the incoming pointer argument has more qualifiers than the
792 argument type it can still be an imperfect match. */
793 if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
794 && !(TYPE_QUALS (TREE_TYPE (in_type))
795 & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
796 && (TYPE_QUALS (TREE_TYPE (b_arg_type))
797 & ~TYPE_QUALS (TREE_TYPE (in_type))))
798 {
799 tree qual_in_type =
800 build_qualified_type (TREE_TYPE (in_type),
801 TYPE_QUALS (TREE_TYPE (b_arg_type)));
802
803 if (lang_hooks.types_compatible_p (qual_in_type,
804 TREE_TYPE (b_arg_type)))
805 {
806 match_type++;
807 continue;
808 }
809 }
810
811 mismatch:
812 if (TARGET_DEBUG_ARG)
813 {
814 fprintf (stderr, " mismatch in operand: %d incoming: ", i + 1);
815 print_generic_expr (stderr, in_type, TDF_VOPS|TDF_MEMSYMS);
816 fprintf (stderr, " expected: ");
817 print_generic_expr (stderr, b_arg_type, TDF_VOPS|TDF_MEMSYMS);
818 fprintf (stderr, "\n");
819 }
820 return INT_MAX;
821 }
822
823 return match_type;
824 }
825
826 /* Return the number of elements in the vector arguments of FNDECL in
827 case all it matches for all vector arguments, -1 otherwise. */
828 static int
829 s390_vec_n_elem (tree fndecl)
830 {
831 tree b_arg_chain;
832 int n_elem = -1;
833
834 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) == VECTOR_TYPE)
835 n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
836
837 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
838 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
839 b_arg_chain = TREE_CHAIN (b_arg_chain))
840 {
841 int tmp_n_elem;
842 if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
843 continue;
844 tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
845 if (n_elem != -1 && n_elem != tmp_n_elem)
846 return -1;
847 n_elem = tmp_n_elem;
848 }
849 return n_elem;
850 }
851
852
853 /* Return a tree expression for a call to the overloaded builtin
854 function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
855 tree
856 s390_resolve_overloaded_builtin (location_t loc,
857 tree ob_fndecl,
858 void *passed_arglist)
859 {
860 vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
861 unsigned int in_args_num = vec_safe_length (arglist);
862 unsigned int ob_args_num = 0;
863 unsigned int ob_fcode = DECL_MD_FUNCTION_CODE (ob_fndecl);
864 enum s390_overloaded_builtin_vars bindex;
865 unsigned int i;
866 int last_match_type = INT_MAX;
867 int last_match_index = -1;
868 unsigned int all_op_flags;
869 const unsigned int ob_flags = bflags_for_builtin(ob_fcode);
870 int num_matches = 0;
871 tree target_builtin_decl, b_arg_chain, return_type;
872 enum s390_builtin_ov_type_index last_match_fntype_index = BT_OV_MAX;
873
874 if (TARGET_DEBUG_ARG)
875 fprintf (stderr,
876 "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
877 (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
878 ob_fcode < S390_BUILTIN_MAX ? "not" : "");
879
880 /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
881 if (ob_fcode < S390_BUILTIN_MAX)
882 {
883 if (ob_flags & B_INT)
884 {
885 error_at (loc,
886 "builtin %qF is for GCC internal use only.",
887 ob_fndecl);
888 return error_mark_node;
889 }
890 return NULL_TREE;
891 }
892
893 if (ob_flags & B_DEP)
894 warning_at (loc, 0, "builtin %qF is deprecated.", ob_fndecl);
895
896 if (!TARGET_VX && (ob_flags & B_VX))
897 {
898 error_at (loc, "%qF requires %<-mvx%>", ob_fndecl);
899 return error_mark_node;
900 }
901
902 if (!TARGET_VXE && (ob_flags & B_VXE))
903 {
904 error_at (loc, "%qF requires z14 or higher", ob_fndecl);
905 return error_mark_node;
906 }
907
908 if (!TARGET_VXE2 && (ob_flags & B_VXE2))
909 {
910 error_at (loc, "%qF requires z15 or higher", ob_fndecl);
911 return error_mark_node;
912 }
913
914 ob_fcode -= S390_BUILTIN_MAX;
915
916 for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
917 !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
918 b_arg_chain = TREE_CHAIN (b_arg_chain))
919 ob_args_num++;
920
921 if (ob_args_num != in_args_num)
922 {
923 error_at (loc,
924 "mismatch in number of arguments for builtin %qF. "
925 "Expected: %d got %d", ob_fndecl,
926 ob_args_num, in_args_num);
927 return error_mark_node;
928 }
929
930 for (i = 0; i < in_args_num; i++)
931 if ((*arglist)[i] == error_mark_node)
932 return error_mark_node;
933
934 /* Overloaded builtins without any variants are directly expanded here. */
935 if (desc_start_for_overloaded_builtin[ob_fcode] ==
936 S390_OVERLOADED_BUILTIN_VAR_MAX)
937 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
938
939 for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
940 bindex <= desc_end_for_overloaded_builtin[ob_fcode];
941 bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
942 {
943 int match_type;
944 enum s390_builtin_ov_type_index type_index =
945 type_for_overloaded_builtin_var[bindex];
946
947 if (TARGET_DEBUG_ARG)
948 fprintf (stderr, "checking variant number: %d", (int)bindex);
949
950 match_type = s390_fn_types_compatible (type_index, arglist);
951
952 if (match_type == INT_MAX)
953 continue;
954
955 if (TARGET_DEBUG_ARG)
956 fprintf (stderr,
957 " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
958 match_type);
959
960 if (match_type < last_match_type)
961 {
962 num_matches = 1;
963 last_match_type = match_type;
964 last_match_fntype_index = type_index;
965 last_match_index = bindex;
966 }
967 else if (match_type == last_match_type)
968 num_matches++;
969 }
970
971 if (last_match_type == INT_MAX)
972 {
973 error_at (loc, "invalid parameter combination for intrinsic %qs",
974 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
975 return error_mark_node;
976 }
977 else if (num_matches > 1)
978 {
979 error_at (loc, "ambiguous overload for intrinsic %qs",
980 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
981 return error_mark_node;
982 }
983
984 if (!TARGET_VXE
985 && bflags_overloaded_builtin_var[last_match_index] & B_VXE)
986 {
987 error_at (loc, "%qs matching variant requires z14 or higher",
988 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
989 return error_mark_node;
990 }
991
992
993 if (!TARGET_VXE2
994 && bflags_overloaded_builtin_var[last_match_index] & B_VXE2)
995 {
996 error_at (loc, "%qs matching variant requires z15 or higher",
997 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
998 return error_mark_node;
999 }
1000
1001 if (bflags_overloaded_builtin_var[last_match_index] & B_DEP)
1002 warning_at (loc, 0, "%qs matching variant is deprecated.",
1003 IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
1004
1005 /* Overloaded variants which have MAX set as low level builtin are
1006 supposed to be replaced during expansion with something else. */
1007 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1008 target_builtin_decl = ob_fndecl;
1009 else
1010 target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
1011
1012 all_op_flags = opflags_overloaded_builtin_var[last_match_index];
1013 return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
1014
1015 /* Check for the operand flags in the overloaded builtin variant. */
1016 for (i = 0; i < ob_args_num; i++)
1017 {
1018 unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
1019 tree arg = (*arglist)[i];
1020 tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
1021
1022 all_op_flags = all_op_flags >> O_SHIFT;
1023
1024 if (op_flags == O_ELEM)
1025 {
1026 int n_elem = s390_vec_n_elem (target_builtin_decl);
1027 gcc_assert (n_elem > 0);
1028 gcc_assert (type == integer_type_node);
1029 (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
1030 fold_convert (integer_type_node, arg),
1031 build_int_cst (NULL_TREE, n_elem - 1));
1032 }
1033
1034 if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
1035 continue;
1036
1037 if ((TYPE_UNSIGNED (type)
1038 && !int_fits_type_p (arg, c_common_unsigned_type (type)))
1039 || (!TYPE_UNSIGNED (type)
1040 && !int_fits_type_p (arg, c_common_signed_type (type))))
1041 {
1042 error("constant argument %d for builtin %qF is out "
1043 "of range for target type",
1044 i + 1, target_builtin_decl);
1045 return error_mark_node;
1046 }
1047
1048 if (TREE_CODE (arg) == INTEGER_CST
1049 && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
1050 return error_mark_node;
1051 }
1052
1053 /* Handle builtins we expand directly - without mapping it to a low
1054 level builtin. */
1055 if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
1056 return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
1057
1058 s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
1059
1060 if (VOID_TYPE_P (return_type))
1061 return build_function_call_vec (loc, vNULL, target_builtin_decl,
1062 arglist, NULL);
1063 else
1064 return fully_fold_convert (return_type,
1065 build_function_call_vec (loc, vNULL, target_builtin_decl,
1066 arglist, NULL));
1067 }
1068
1069 /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
1070 void
1071 s390_register_target_pragmas (void)
1072 {
1073 targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
1074 #if S390_USE_TARGET_ATTRIBUTE
1075 /* Update pragma hook to allow parsing #pragma GCC target. */
1076 targetm.target_option.pragma_parse = s390_pragma_target_parse;
1077 #endif
1078 }