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