xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/s390/s390-c.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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