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