s390-c.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. /* Language specific subroutines used for code generation on IBM S/390
  2. and zSeries
  3. Copyright (C) 2015 Free Software Foundation, Inc.
  4. Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
  5. This file is part of GCC.
  6. GCC is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3, or (at your option)
  9. any later version.
  10. GCC is distributed in the hope that it will be useful, but WITHOUT
  11. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  13. License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with GCC; see the file COPYING3. If not see
  16. <http://www.gnu.org/licenses/>.
  17. Based on gcc/config/rs6000/rs6000-c.c.
  18. In GCC terms this file belongs to the frontend. It will be
  19. compiled with -DIN_GCC_FRONTEND. With that rtl.h cannot be
  20. included anymore - a mechanism supposed to avoid adding frontend -
  21. backend dependencies. */
  22. #include "config.h"
  23. #include "system.h"
  24. #include "coretypes.h"
  25. #include "tm.h"
  26. #include "cpplib.h"
  27. #include "hash-set.h"
  28. #include "machmode.h"
  29. #include "vec.h"
  30. #include "double-int.h"
  31. #include "input.h"
  32. #include "alias.h"
  33. #include "symtab.h"
  34. #include "wide-int.h"
  35. #include "inchash.h"
  36. #include "tree.h"
  37. #include "fold-const.h"
  38. #include "stringpool.h"
  39. #include "c-family/c-common.h"
  40. #include "c-family/c-pragma.h"
  41. #include "diagnostic-core.h"
  42. #include "tm_p.h"
  43. #include "target.h"
  44. #include "langhooks.h"
  45. #include "tree-pretty-print.h"
  46. #include "c/c-tree.h"
  47. #include "s390-builtins.h"
  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. /* Generate an array holding all the descriptions of variants of
  54. overloaded builtins defined with OB_DEF_VAR in
  55. s390-builtins.def. */
  56. static enum s390_builtin_ov_type_index
  57. type_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX + 1] =
  58. {
  59. #undef B_DEF
  60. #undef OB_DEF
  61. #undef OB_DEF_VAR
  62. #define B_DEF(...)
  63. #define OB_DEF(...)
  64. #define OB_DEF_VAR(NAME, PATTERN, FLAGS, FNTYPE) FNTYPE,
  65. #include "s390-builtins.def"
  66. BT_OV_MAX
  67. };
  68. /* Generate an array indexed by an overloaded builtin index returning
  69. the first index in desc_for_overloaded_builtin_var where the
  70. variants for the builtin can be found. */
  71. static enum s390_overloaded_builtin_vars
  72. desc_start_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
  73. {
  74. #undef B_DEF
  75. #undef OB_DEF
  76. #undef OB_DEF_VAR
  77. #define B_DEF(...)
  78. #define OB_DEF(NAME, FIRST_VAR_NAME,...) \
  79. S390_OVERLOADED_BUILTIN_VAR_##FIRST_VAR_NAME,
  80. #define OB_DEF_VAR(...)
  81. #include "s390-builtins.def"
  82. S390_OVERLOADED_BUILTIN_VAR_MAX
  83. };
  84. /* Generate an array indexed by an overloaded builtin index returning
  85. the last index in desc_for_overloaded_builtin_var where the
  86. variants for the builtin can be found. */
  87. static enum s390_overloaded_builtin_vars
  88. desc_end_for_overloaded_builtin[S390_OVERLOADED_BUILTIN_MAX + 1] =
  89. {
  90. #undef B_DEF
  91. #undef OB_DEF
  92. #undef OB_DEF_VAR
  93. #define B_DEF(...)
  94. #define OB_DEF(NAME, FIRST_VAR_NAME, LAST_VAR_NAME,...) \
  95. S390_OVERLOADED_BUILTIN_VAR_##LAST_VAR_NAME,
  96. #define OB_DEF_VAR(...)
  97. #include "s390-builtins.def"
  98. S390_OVERLOADED_BUILTIN_VAR_MAX
  99. };
  100. static enum s390_builtin_type_index
  101. s390_builtin_ov_types[BT_OV_MAX][MAX_OV_OPERANDS] =
  102. {
  103. #undef DEF_TYPE
  104. #undef DEF_POINTER_TYPE
  105. #undef DEF_DISTINCT_TYPE
  106. #undef DEF_VECTOR_TYPE
  107. #undef DEF_OPAQUE_VECTOR_TYPE
  108. #undef DEF_FN_TYPE
  109. #undef DEF_OV_TYPE
  110. #define DEF_TYPE(...)
  111. #define DEF_POINTER_TYPE(...)
  112. #define DEF_DISTINCT_TYPE(...)
  113. #define DEF_VECTOR_TYPE(...)
  114. #define DEF_OPAQUE_VECTOR_TYPE(...)
  115. #define DEF_FN_TYPE(...)
  116. #define DEF_OV_TYPE(INDEX, args...) { args },
  117. #include "s390-builtin-types.def"
  118. };
  119. static const enum s390_builtins
  120. bt_for_overloaded_builtin_var[S390_OVERLOADED_BUILTIN_VAR_MAX] = {
  121. #undef B_DEF
  122. #undef OB_DEF
  123. #undef OB_DEF_VAR
  124. #define B_DEF(...)
  125. #define OB_DEF(...)
  126. #define OB_DEF_VAR(NAME, BT, ...) S390_BUILTIN_##BT,
  127. #include "s390-builtins.def"
  128. };
  129. /* In addition to calling fold_convert for EXPR of type TYPE, also
  130. call c_fully_fold to remove any C_MAYBE_CONST_EXPRs that could be
  131. hiding there (PR47197). */
  132. tree
  133. fully_fold_convert (tree type, tree expr)
  134. {
  135. tree result = fold_convert (type, expr);
  136. bool maybe_const = true;
  137. if (!c_dialect_cxx ())
  138. result = c_fully_fold (result, false, &maybe_const);
  139. return result;
  140. }
  141. /* Unify the different variants to the same nodes in order to keep the
  142. code working with it simple. */
  143. static cpp_hashnode *
  144. s390_categorize_keyword (const cpp_token *tok)
  145. {
  146. if (tok->type == CPP_NAME)
  147. {
  148. cpp_hashnode *ident = tok->val.node.node;
  149. if (ident == C_CPP_HASHNODE (vector_keyword))
  150. return C_CPP_HASHNODE (__vector_keyword);
  151. if (ident == C_CPP_HASHNODE (bool_keyword))
  152. return C_CPP_HASHNODE (__bool_keyword);
  153. if (ident == C_CPP_HASHNODE (_Bool_keyword))
  154. return C_CPP_HASHNODE (__bool_keyword);
  155. return ident;
  156. }
  157. return 0;
  158. }
  159. /* Called to decide whether a conditional macro should be expanded.
  160. Since we have exactly one such macro (i.e, 'vector'), we do not
  161. need to examine the 'tok' parameter. */
  162. static cpp_hashnode *
  163. s390_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
  164. {
  165. cpp_hashnode *expand_this = tok->val.node.node;
  166. cpp_hashnode *ident;
  167. static bool expand_bool_p = false;
  168. int idx = 0;
  169. enum rid rid_code;
  170. /* The vector keyword is only expanded if the machine actually
  171. provides hardware support. */
  172. if (!TARGET_ZVECTOR)
  173. return NULL;
  174. ident = s390_categorize_keyword (tok);
  175. /* Triggered when we picked a different variant in
  176. s390_categorize_keyword. */
  177. if (ident != expand_this)
  178. expand_this = NULL;
  179. /* The vector keyword has been found already and we remembered to
  180. expand the next bool. */
  181. if (expand_bool_p && ident == C_CPP_HASHNODE (__bool_keyword))
  182. {
  183. expand_bool_p = false;
  184. return ident;
  185. }
  186. if (ident != C_CPP_HASHNODE (__vector_keyword))
  187. return expand_this;
  188. do
  189. tok = cpp_peek_token (pfile, idx++);
  190. while (tok->type == CPP_PADDING);
  191. ident = s390_categorize_keyword (tok);
  192. if (!ident)
  193. return expand_this;
  194. /* vector bool - remember to expand the next bool. */
  195. if (ident == C_CPP_HASHNODE (__bool_keyword))
  196. {
  197. expand_bool_p = true;
  198. return C_CPP_HASHNODE (__vector_keyword);
  199. }
  200. /* The boost libraries have code with Iterator::vector vector in it.
  201. If we allow the normal handling, this module will be called
  202. recursively, and the vector will be skipped.; */
  203. if (ident == C_CPP_HASHNODE (__vector_keyword))
  204. return expand_this;
  205. rid_code = (enum rid)(ident->rid_code);
  206. if (ident->type == NT_MACRO)
  207. {
  208. /* Now actually fetch the tokens we "peeked" before and do a
  209. lookahead for the next. */
  210. do
  211. (void) cpp_get_token (pfile);
  212. while (--idx > 0);
  213. do
  214. tok = cpp_peek_token (pfile, idx++);
  215. while (tok->type == CPP_PADDING);
  216. ident = s390_categorize_keyword (tok);
  217. if (ident == C_CPP_HASHNODE (__bool_keyword))
  218. {
  219. expand_bool_p = true;
  220. return C_CPP_HASHNODE (__vector_keyword);
  221. }
  222. else if (ident)
  223. rid_code = (enum rid)(ident->rid_code);
  224. }
  225. /* vector keyword followed by type identifier: vector unsigned,
  226. vector long, ...
  227. Types consisting of more than one identifier are not supported by
  228. zvector e.g. long long, long double, unsigned long int. */
  229. if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
  230. || rid_code == RID_SHORT || rid_code == RID_SIGNED
  231. || rid_code == RID_INT || rid_code == RID_CHAR
  232. || rid_code == RID_DOUBLE)
  233. {
  234. expand_this = C_CPP_HASHNODE (__vector_keyword);
  235. /* If the next keyword is bool, it will need to be expanded as
  236. well. */
  237. do
  238. tok = cpp_peek_token (pfile, idx++);
  239. while (tok->type == CPP_PADDING);
  240. ident = s390_categorize_keyword (tok);
  241. /* __vector long __bool a; */
  242. if (ident == C_CPP_HASHNODE (__bool_keyword))
  243. expand_bool_p = true;
  244. else
  245. {
  246. /* Triggered with: __vector long long __bool a; */
  247. do
  248. tok = cpp_peek_token (pfile, idx++);
  249. while (tok->type == CPP_PADDING);
  250. ident = s390_categorize_keyword (tok);
  251. if (ident == C_CPP_HASHNODE (__bool_keyword))
  252. expand_bool_p = true;
  253. }
  254. }
  255. return expand_this;
  256. }
  257. /* Define platform dependent macros. */
  258. void
  259. s390_cpu_cpp_builtins (cpp_reader *pfile)
  260. {
  261. cpp_assert (pfile, "cpu=s390");
  262. cpp_assert (pfile, "machine=s390");
  263. cpp_define (pfile, "__s390__");
  264. if (TARGET_ZARCH)
  265. cpp_define (pfile, "__zarch__");
  266. if (TARGET_64BIT)
  267. cpp_define (pfile, "__s390x__");
  268. if (TARGET_LONG_DOUBLE_128)
  269. cpp_define (pfile, "__LONG_DOUBLE_128__");
  270. if (TARGET_HTM)
  271. cpp_define (pfile, "__HTM__");
  272. if (TARGET_ZVECTOR)
  273. {
  274. cpp_define (pfile, "__VEC__=10301");
  275. cpp_define (pfile, "__vector=__attribute__((vector_size(16)))");
  276. cpp_define (pfile, "__bool=__attribute__((s390_vector_bool)) unsigned");
  277. if (!flag_iso)
  278. {
  279. cpp_define (pfile, "__VECTOR_KEYWORD_SUPPORTED__");
  280. cpp_define (pfile, "vector=vector");
  281. cpp_define (pfile, "bool=bool");
  282. __vector_keyword = get_identifier ("__vector");
  283. C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
  284. vector_keyword = get_identifier ("vector");
  285. C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
  286. __bool_keyword = get_identifier ("__bool");
  287. C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
  288. bool_keyword = get_identifier ("bool");
  289. C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
  290. _Bool_keyword = get_identifier ("_Bool");
  291. C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
  292. /* Enable context-sensitive macros. */
  293. cpp_get_callbacks (pfile)->macro_to_expand = s390_macro_to_expand;
  294. }
  295. }
  296. }
  297. /* Expand builtins which can directly be mapped to tree expressions.
  298. LOC - location information
  299. FCODE - function code of the builtin
  300. ARGLIST - value supposed to be passed as arguments
  301. RETURN-TYPE - expected return type of the builtin */
  302. static tree
  303. s390_expand_overloaded_builtin (location_t loc,
  304. unsigned fcode,
  305. vec<tree, va_gc> *arglist,
  306. tree return_type)
  307. {
  308. switch (fcode)
  309. {
  310. case S390_OVERLOADED_BUILTIN_s390_vec_step:
  311. if (TREE_CODE (TREE_TYPE ((*arglist)[0])) != VECTOR_TYPE)
  312. {
  313. error_at (loc, "Builtin vec_step can only be used on vector types.");
  314. return error_mark_node;
  315. }
  316. return build_int_cst (NULL_TREE,
  317. TYPE_VECTOR_SUBPARTS (TREE_TYPE ((*arglist)[0])));
  318. case S390_OVERLOADED_BUILTIN_s390_vec_xld2:
  319. case S390_OVERLOADED_BUILTIN_s390_vec_xlw4:
  320. return build2 (MEM_REF, return_type,
  321. fold_build_pointer_plus ((*arglist)[1], (*arglist)[0]),
  322. build_int_cst (TREE_TYPE ((*arglist)[1]), 0));
  323. case S390_OVERLOADED_BUILTIN_s390_vec_xstd2:
  324. case S390_OVERLOADED_BUILTIN_s390_vec_xstw4:
  325. return build2 (MODIFY_EXPR, TREE_TYPE((*arglist)[0]),
  326. build1 (INDIRECT_REF, TREE_TYPE((*arglist)[0]),
  327. fold_build_pointer_plus ((*arglist)[2], (*arglist)[1])),
  328. (*arglist)[0]);
  329. case S390_OVERLOADED_BUILTIN_s390_vec_load_pair:
  330. return build_constructor_va (return_type, 2,
  331. NULL_TREE, (*arglist)[0],
  332. NULL_TREE, (*arglist)[1]);
  333. default:
  334. gcc_unreachable ();
  335. }
  336. }
  337. /* invert result */
  338. #define __VSTRING_FLAG_IN 8
  339. /* result type */
  340. #define __VSTRING_FLAG_RT 4
  341. /* zero search */
  342. #define __VSTRING_FLAG_ZS 2
  343. /* set condition code */
  344. #define __VSTRING_FLAG_CS 1
  345. /* Return the flags value to be used for string low-level builtins
  346. when expanded from overloaded builtin OB_FCODE. */
  347. static unsigned int
  348. s390_get_vstring_flags (int ob_fcode)
  349. {
  350. unsigned int flags = 0;
  351. switch (ob_fcode)
  352. {
  353. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
  354. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
  355. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
  356. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
  357. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
  358. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
  359. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
  360. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
  361. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
  362. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
  363. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
  364. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
  365. flags |= __VSTRING_FLAG_IN;
  366. break;
  367. default:
  368. break;
  369. }
  370. switch (ob_fcode)
  371. {
  372. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
  373. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
  374. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
  375. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
  376. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
  377. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
  378. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
  379. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
  380. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
  381. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
  382. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
  383. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
  384. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
  385. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
  386. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
  387. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
  388. flags |= __VSTRING_FLAG_RT;
  389. break;
  390. default:
  391. break;
  392. }
  393. switch (ob_fcode)
  394. {
  395. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
  396. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
  397. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
  398. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
  399. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
  400. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
  401. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
  402. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
  403. flags |= __VSTRING_FLAG_ZS;
  404. break;
  405. default:
  406. break;
  407. }
  408. switch (ob_fcode)
  409. {
  410. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
  411. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
  412. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
  413. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
  414. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
  415. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
  416. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
  417. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
  418. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
  419. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
  420. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
  421. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
  422. flags |= __VSTRING_FLAG_CS;
  423. break;
  424. default:
  425. break;
  426. }
  427. return flags;
  428. }
  429. #undef __VSTRING_FLAG_IN
  430. #undef __VSTRING_FLAG_RT
  431. #undef __VSTRING_FLAG_ZS
  432. #undef __VSTRING_FLAG_CS
  433. /* For several overloaded builtins the argument lists do not match
  434. exactly the signature of a low-level builtin. This function
  435. adjusts the argument list ARGLIST for the overloaded builtin
  436. OB_FCODE to the signature of the low-level builtin given by
  437. DECL. */
  438. static void
  439. s390_adjust_builtin_arglist (unsigned int ob_fcode, tree decl,
  440. vec<tree, va_gc> **arglist)
  441. {
  442. tree arg_chain;
  443. int src_arg_index, dest_arg_index;
  444. vec<tree, va_gc> *folded_args = NULL;
  445. /* We at most add one more operand to the list. */
  446. vec_alloc (folded_args, (*arglist)->allocated () + 1);
  447. for (arg_chain = TYPE_ARG_TYPES (TREE_TYPE (decl)),
  448. src_arg_index = 0, dest_arg_index = 0;
  449. !VOID_TYPE_P (TREE_VALUE (arg_chain));
  450. arg_chain = TREE_CHAIN (arg_chain), dest_arg_index++)
  451. {
  452. bool arg_assigned_p = false;
  453. switch (ob_fcode)
  454. {
  455. /* For all these the low level builtin needs an additional flags parameter. */
  456. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx:
  457. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx:
  458. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx:
  459. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx:
  460. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq:
  461. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne:
  462. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_idx_cc:
  463. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_idx_cc:
  464. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_or_0_idx_cc:
  465. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_or_0_idx_cc:
  466. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_eq_cc:
  467. case S390_OVERLOADED_BUILTIN_s390_vec_find_any_ne_cc:
  468. if (dest_arg_index == 2)
  469. {
  470. folded_args->quick_push (build_int_cst (integer_type_node,
  471. s390_get_vstring_flags (ob_fcode)));
  472. arg_assigned_p = true;
  473. }
  474. break;
  475. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx:
  476. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx:
  477. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx:
  478. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx:
  479. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg:
  480. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg:
  481. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_idx_cc:
  482. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_idx_cc:
  483. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_or_0_idx_cc:
  484. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_or_0_idx_cc:
  485. case S390_OVERLOADED_BUILTIN_s390_vec_cmprg_cc:
  486. case S390_OVERLOADED_BUILTIN_s390_vec_cmpnrg_cc:
  487. if (dest_arg_index == 3)
  488. {
  489. folded_args->quick_push (build_int_cst (integer_type_node,
  490. s390_get_vstring_flags (ob_fcode)));
  491. arg_assigned_p = true;
  492. }
  493. break;
  494. case S390_OVERLOADED_BUILTIN_s390_vec_sel:
  495. case S390_OVERLOADED_BUILTIN_s390_vec_insert:
  496. case S390_OVERLOADED_BUILTIN_s390_vec_load_len:
  497. /* Swap the first to arguments. It is better to do it here
  498. instead of the header file to avoid operand checking
  499. throwing error messages for a weird operand index. */
  500. if (dest_arg_index < 2)
  501. {
  502. folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
  503. (**arglist)[1 - dest_arg_index]));
  504. src_arg_index++;
  505. arg_assigned_p = true;
  506. }
  507. break;
  508. case S390_OVERLOADED_BUILTIN_s390_vec_store_len:
  509. if (dest_arg_index == 1 || dest_arg_index == 2)
  510. {
  511. folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
  512. (**arglist)[3 - dest_arg_index]));
  513. src_arg_index++;
  514. arg_assigned_p = true;
  515. }
  516. break;
  517. case S390_OVERLOADED_BUILTIN_s390_vec_load_bndry:
  518. {
  519. int code;
  520. if (dest_arg_index == 1)
  521. {
  522. switch (tree_to_uhwi ((**arglist)[src_arg_index]))
  523. {
  524. case 64: code = 0; break;
  525. case 128: code = 1; break;
  526. case 256: code = 2; break;
  527. case 512: code = 3; break;
  528. case 1024: code = 4; break;
  529. case 2048: code = 5; break;
  530. case 4096: code = 6; break;
  531. default:
  532. error ("valid values for builtin %qF argument %d are 64, "
  533. "128, 256, 512, 1024, 2048, and 4096", decl,
  534. src_arg_index + 1);
  535. return;
  536. }
  537. folded_args->quick_push (build_int_cst (integer_type_node,
  538. code));
  539. src_arg_index++;
  540. arg_assigned_p = true;
  541. }
  542. }
  543. break;
  544. case S390_OVERLOADED_BUILTIN_s390_vec_rl_mask:
  545. /* Duplicate the first src arg. */
  546. if (dest_arg_index == 0)
  547. {
  548. folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
  549. (**arglist)[src_arg_index]));
  550. arg_assigned_p = true;
  551. }
  552. break;
  553. default:
  554. break;
  555. }
  556. if (!arg_assigned_p)
  557. {
  558. folded_args->quick_push (fully_fold_convert (TREE_VALUE (arg_chain),
  559. (**arglist)[src_arg_index]));
  560. src_arg_index++;
  561. }
  562. }
  563. *arglist = folded_args;
  564. }
  565. /* Check whether the arguments in ARGLIST match the function type
  566. DEF_TYPE. Return the number of argument types which required
  567. conversion/promotion in order to make it match.
  568. 0 stands for a perfect match - all operand types match without changes
  569. INT_MAX stands for a mismatch. */
  570. static int
  571. s390_fn_types_compatible (enum s390_builtin_ov_type_index typeindex,
  572. vec<tree, va_gc> *arglist)
  573. {
  574. unsigned int i;
  575. int match_type = 0;
  576. for (i = 0; i < vec_safe_length (arglist); i++)
  577. {
  578. tree b_arg_type = s390_builtin_types[s390_builtin_ov_types[typeindex][i + 1]];
  579. tree in_arg = (*arglist)[i];
  580. tree in_type = TREE_TYPE (in_arg);
  581. if (TREE_CODE (b_arg_type) == VECTOR_TYPE)
  582. {
  583. /* Vector types have to match precisely. */
  584. if (b_arg_type != in_type
  585. && TYPE_MAIN_VARIANT (b_arg_type) != TYPE_MAIN_VARIANT (in_type))
  586. goto mismatch;
  587. }
  588. if (lang_hooks.types_compatible_p (in_type, b_arg_type))
  589. continue;
  590. if (lang_hooks.types_compatible_p (
  591. lang_hooks.types.type_promotes_to (in_type),
  592. lang_hooks.types.type_promotes_to (b_arg_type)))
  593. {
  594. match_type++;
  595. continue;
  596. }
  597. /* In this stage the C++ frontend would go ahead trying to find
  598. implicit conversion chains for the argument to match the
  599. target type. We will mimic this here only for our limited
  600. subset of argument types. */
  601. if (TREE_CODE (b_arg_type) == INTEGER_TYPE
  602. && TREE_CODE (in_type) == INTEGER_TYPE)
  603. {
  604. match_type++;
  605. continue;
  606. }
  607. /* If the incoming pointer argument has more qualifiers than the
  608. argument type it can still be an imperfect match. */
  609. if (POINTER_TYPE_P (b_arg_type) && POINTER_TYPE_P (in_type)
  610. && !(TYPE_QUALS (TREE_TYPE (in_type))
  611. & ~TYPE_QUALS (TREE_TYPE (b_arg_type)))
  612. && (TYPE_QUALS (TREE_TYPE (b_arg_type))
  613. & ~TYPE_QUALS (TREE_TYPE (in_type))))
  614. {
  615. tree qual_in_type =
  616. build_qualified_type (TREE_TYPE (in_type),
  617. TYPE_QUALS (TREE_TYPE (b_arg_type)));
  618. if (lang_hooks.types_compatible_p (qual_in_type,
  619. TREE_TYPE (b_arg_type)))
  620. {
  621. match_type++;
  622. continue;
  623. }
  624. }
  625. mismatch:
  626. if (TARGET_DEBUG_ARG)
  627. fprintf (stderr, " mismatch in operand: %d\n", i + 1);
  628. return INT_MAX;
  629. }
  630. return match_type;
  631. }
  632. /* Return the number of elements in the vector arguments of FNDECL in
  633. case all it matches for all vector arguments, -1 otherwise. */
  634. static int
  635. s390_vec_n_elem (tree fndecl)
  636. {
  637. tree b_arg_chain;
  638. int n_elem = -1;
  639. if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) == VECTOR_TYPE)
  640. n_elem = TYPE_VECTOR_SUBPARTS (TREE_TYPE (TREE_TYPE ((fndecl))));
  641. for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
  642. !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
  643. b_arg_chain = TREE_CHAIN (b_arg_chain))
  644. {
  645. int tmp_n_elem;
  646. if (TREE_CODE (TREE_VALUE (b_arg_chain)) != VECTOR_TYPE)
  647. continue;
  648. tmp_n_elem = TYPE_VECTOR_SUBPARTS (TREE_VALUE (b_arg_chain));
  649. if (n_elem != -1 && n_elem != tmp_n_elem)
  650. return -1;
  651. n_elem = tmp_n_elem;
  652. }
  653. return n_elem;
  654. }
  655. /* Return a tree expression for a call to the overloaded builtin
  656. function OB_FNDECL at LOC with arguments PASSED_ARGLIST. */
  657. tree
  658. s390_resolve_overloaded_builtin (location_t loc,
  659. tree ob_fndecl,
  660. void *passed_arglist)
  661. {
  662. vec<tree, va_gc> *arglist = static_cast<vec<tree, va_gc> *> (passed_arglist);
  663. unsigned int in_args_num = vec_safe_length (arglist);
  664. unsigned int ob_args_num = 0;
  665. unsigned int ob_fcode = DECL_FUNCTION_CODE (ob_fndecl);
  666. enum s390_overloaded_builtin_vars bindex;
  667. unsigned int i;
  668. int last_match_type = INT_MAX;
  669. int last_match_index = -1;
  670. unsigned int all_op_flags;
  671. int num_matches = 0;
  672. tree target_builtin_decl, b_arg_chain, return_type;
  673. enum s390_builtin_ov_type_index last_match_fntype_index;
  674. if (TARGET_DEBUG_ARG)
  675. fprintf (stderr,
  676. "s390_resolve_overloaded_builtin, code = %4d, %s - %s overloaded\n",
  677. (int)ob_fcode, IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)),
  678. ob_fcode < S390_BUILTIN_MAX ? "not" : "");
  679. /* 0...S390_BUILTIN_MAX-1 is for non-overloaded builtins. */
  680. if (ob_fcode < S390_BUILTIN_MAX)
  681. {
  682. if (bflags_for_builtin(ob_fcode) & B_INT)
  683. {
  684. error_at (loc,
  685. "Builtin %qF is for GCC internal use only.",
  686. ob_fndecl);
  687. return error_mark_node;
  688. }
  689. return NULL_TREE;
  690. }
  691. ob_fcode -= S390_BUILTIN_MAX;
  692. for (b_arg_chain = TYPE_ARG_TYPES (TREE_TYPE (ob_fndecl));
  693. !VOID_TYPE_P (TREE_VALUE (b_arg_chain));
  694. b_arg_chain = TREE_CHAIN (b_arg_chain))
  695. ob_args_num++;
  696. if (ob_args_num != in_args_num)
  697. {
  698. error_at (loc,
  699. "Mismatch in number of arguments for builtin %qF. "
  700. "Expected: %d got %d", ob_fndecl,
  701. ob_args_num, in_args_num);
  702. return error_mark_node;
  703. }
  704. for (i = 0; i < in_args_num; i++)
  705. if ((*arglist)[i] == error_mark_node)
  706. return error_mark_node;
  707. /* Overloaded builtins without any variants are directly expanded here. */
  708. if (desc_start_for_overloaded_builtin[ob_fcode] ==
  709. S390_OVERLOADED_BUILTIN_VAR_MAX)
  710. return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, NULL_TREE);
  711. for (bindex = desc_start_for_overloaded_builtin[ob_fcode];
  712. bindex <= desc_end_for_overloaded_builtin[ob_fcode];
  713. bindex = (enum s390_overloaded_builtin_vars)((int)bindex + 1))
  714. {
  715. int match_type;
  716. enum s390_builtin_ov_type_index type_index =
  717. type_for_overloaded_builtin_var[bindex];
  718. if (TARGET_DEBUG_ARG)
  719. fprintf (stderr, "checking variant number: %d", (int)bindex);
  720. match_type = s390_fn_types_compatible (type_index, arglist);
  721. if (match_type == INT_MAX)
  722. continue;
  723. if (TARGET_DEBUG_ARG)
  724. fprintf (stderr,
  725. " %s match score: %d\n", match_type == 0 ? "perfect" : "imperfect",
  726. match_type);
  727. if (match_type < last_match_type)
  728. {
  729. num_matches = 1;
  730. last_match_type = match_type;
  731. last_match_fntype_index = type_index;
  732. last_match_index = bindex;
  733. }
  734. else if (match_type == last_match_type)
  735. num_matches++;
  736. }
  737. if (last_match_type == INT_MAX)
  738. {
  739. error_at (loc, "invalid parameter combination for intrinsic");
  740. return error_mark_node;
  741. }
  742. else if (num_matches > 1)
  743. {
  744. error_at (loc, "ambiguous overload for intrinsic: %s\n",
  745. IDENTIFIER_POINTER (DECL_NAME (ob_fndecl)));
  746. return error_mark_node;
  747. }
  748. if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
  749. target_builtin_decl = ob_fndecl;
  750. else
  751. target_builtin_decl = s390_builtin_decls[bt_for_overloaded_builtin_var[last_match_index]];
  752. all_op_flags = opflags_overloaded_builtin_var[last_match_index];
  753. return_type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][0]];
  754. /* Check for the operand flags in the overloaded builtin variant. */
  755. for (i = 0; i < ob_args_num; i++)
  756. {
  757. unsigned int op_flags = all_op_flags & ((1 << O_SHIFT) - 1);
  758. tree arg = (*arglist)[i];
  759. tree type = s390_builtin_types[s390_builtin_ov_types[last_match_fntype_index][i + 1]];
  760. all_op_flags = all_op_flags >> O_SHIFT;
  761. if (op_flags == O_ELEM)
  762. {
  763. int n_elem = s390_vec_n_elem (target_builtin_decl);
  764. gcc_assert (n_elem > 0);
  765. gcc_assert (type == integer_type_node);
  766. (*arglist)[i] = build2 (BIT_AND_EXPR, integer_type_node,
  767. fold_convert (integer_type_node, arg),
  768. build_int_cst (NULL_TREE, n_elem - 1));
  769. }
  770. if (TREE_CODE (arg) != INTEGER_CST || !O_IMM_P (op_flags))
  771. continue;
  772. if ((TYPE_UNSIGNED (type)
  773. && !int_fits_type_p (arg, c_common_unsigned_type (type)))
  774. || (!TYPE_UNSIGNED (type)
  775. && !int_fits_type_p (arg, c_common_signed_type (type))))
  776. {
  777. error("constant argument %d for builtin %qF is out "
  778. "of range for target type",
  779. i + 1, target_builtin_decl);
  780. return error_mark_node;
  781. }
  782. if (TREE_CODE (arg) == INTEGER_CST
  783. && !s390_const_operand_ok (arg, i + 1, op_flags, target_builtin_decl))
  784. return error_mark_node;
  785. }
  786. /* Handle builtins we expand directly - without mapping it to a low
  787. level builtin. */
  788. if (bt_for_overloaded_builtin_var[last_match_index] == S390_BUILTIN_MAX)
  789. return s390_expand_overloaded_builtin (loc, ob_fcode, arglist, return_type);
  790. s390_adjust_builtin_arglist (ob_fcode, target_builtin_decl, &arglist);
  791. if (VOID_TYPE_P (return_type))
  792. return build_function_call_vec (loc, vNULL, target_builtin_decl,
  793. arglist, NULL);
  794. else
  795. return fully_fold_convert (return_type,
  796. build_function_call_vec (loc, vNULL, target_builtin_decl,
  797. arglist, NULL));
  798. }
  799. /* This is used to define the REGISTER_TARGET_PRAGMAS macro in s390.h. */
  800. void
  801. s390_register_target_pragmas (void)
  802. {
  803. targetm.resolve_overloaded_builtin = s390_resolve_overloaded_builtin;
  804. }