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