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