1 1.1 mrg /* intrinsics.cc -- D language compiler intrinsics. 2 1.1.1.3 mrg Copyright (C) 2006-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg GCC is free software; you can redistribute it and/or modify 5 1.1 mrg it under the terms of the GNU General Public License as published by 6 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 7 1.1 mrg any later version. 8 1.1 mrg 9 1.1 mrg GCC is distributed in the hope that it will be useful, 10 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 11 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 1.1 mrg GNU General Public License for more details. 13 1.1 mrg 14 1.1 mrg You should have received a copy of the GNU General Public License 15 1.1 mrg along with GCC; see the file COPYING3. If not see 16 1.1 mrg <http://www.gnu.org/licenses/>. */ 17 1.1 mrg 18 1.1 mrg #include "config.h" 19 1.1 mrg #include "system.h" 20 1.1 mrg #include "coretypes.h" 21 1.1 mrg 22 1.1 mrg #include "dmd/declaration.h" 23 1.1.1.3 mrg #include "dmd/expression.h" 24 1.1 mrg #include "dmd/identifier.h" 25 1.1 mrg #include "dmd/mangle.h" 26 1.1 mrg #include "dmd/module.h" 27 1.1 mrg #include "dmd/template.h" 28 1.1 mrg 29 1.1 mrg #include "tm.h" 30 1.1 mrg #include "function.h" 31 1.1 mrg #include "tree.h" 32 1.1 mrg #include "fold-const.h" 33 1.1 mrg #include "stringpool.h" 34 1.1 mrg #include "builtins.h" 35 1.1 mrg 36 1.1 mrg #include "d-tree.h" 37 1.1 mrg 38 1.1 mrg 39 1.1 mrg /* An internal struct used to hold information on D intrinsics. */ 40 1.1 mrg 41 1.1 mrg struct intrinsic_decl 42 1.1 mrg { 43 1.1.1.3 mrg /* The DECL_INTRINSIC_CODE of this decl. */ 44 1.1 mrg intrinsic_code code; 45 1.1 mrg 46 1.1.1.3 mrg /* The DECL_FUNCTION_CODE of this decl, if it directly maps to any. */ 47 1.1.1.3 mrg built_in_function built_in; 48 1.1.1.3 mrg 49 1.1 mrg /* The name of the intrinsic. */ 50 1.1 mrg const char *name; 51 1.1 mrg 52 1.1 mrg /* The module where the intrinsic is located. */ 53 1.1 mrg const char *module; 54 1.1 mrg 55 1.1 mrg /* The mangled signature decoration of the intrinsic. */ 56 1.1 mrg const char *deco; 57 1.1 mrg 58 1.1 mrg /* True if the intrinsic is only handled in CTFE. */ 59 1.1 mrg bool ctfeonly; 60 1.1 mrg }; 61 1.1 mrg 62 1.1 mrg static const intrinsic_decl intrinsic_decls[] = 63 1.1 mrg { 64 1.1.1.3 mrg #define DEF_D_INTRINSIC(CODE, BUILTIN, NAME, MODULE, DECO, CTFE) \ 65 1.1.1.3 mrg { CODE, BUILTIN, NAME, MODULE, DECO, CTFE }, 66 1.1 mrg 67 1.1 mrg #include "intrinsics.def" 68 1.1 mrg 69 1.1 mrg #undef DEF_D_INTRINSIC 70 1.1 mrg }; 71 1.1 mrg 72 1.1 mrg /* Checks if DECL is an intrinsic or run time library function that requires 73 1.1 mrg special processing. Sets DECL_INTRINSIC_CODE so it can be identified 74 1.1 mrg later in maybe_expand_intrinsic. */ 75 1.1 mrg 76 1.1 mrg void 77 1.1 mrg maybe_set_intrinsic (FuncDeclaration *decl) 78 1.1 mrg { 79 1.1.1.3 mrg if (!decl->ident || decl->builtin != BUILTIN::unknown) 80 1.1 mrg return; 81 1.1 mrg 82 1.1 mrg /* The builtin flag is updated only if we can evaluate the intrinsic 83 1.1 mrg at compile-time. Such as the math or bitop intrinsics. */ 84 1.1.1.3 mrg decl->builtin = BUILTIN::unimp; 85 1.1 mrg 86 1.1 mrg /* Check if it's a compiler intrinsic. We only require that any 87 1.1 mrg internally recognised intrinsics are declared in a module with 88 1.1 mrg an explicit module declaration. */ 89 1.1 mrg Module *m = decl->getModule (); 90 1.1 mrg 91 1.1 mrg if (!m || !m->md) 92 1.1 mrg return; 93 1.1 mrg 94 1.1 mrg TemplateInstance *ti = decl->isInstantiated (); 95 1.1 mrg TemplateDeclaration *td = ti ? ti->tempdecl->isTemplateDeclaration () : NULL; 96 1.1 mrg 97 1.1 mrg const char *tname = decl->ident->toChars (); 98 1.1 mrg const char *tmodule = m->md->toChars (); 99 1.1 mrg const char *tdeco = (td == NULL) ? decl->type->deco : NULL; 100 1.1 mrg 101 1.1 mrg /* Look through all D intrinsics. */ 102 1.1 mrg for (size_t i = 0; i < (int) INTRINSIC_LAST; i++) 103 1.1 mrg { 104 1.1 mrg if (!intrinsic_decls[i].name) 105 1.1 mrg continue; 106 1.1 mrg 107 1.1 mrg if (strcmp (intrinsic_decls[i].name, tname) != 0 108 1.1 mrg || strcmp (intrinsic_decls[i].module, tmodule) != 0) 109 1.1 mrg continue; 110 1.1 mrg 111 1.1 mrg /* Instantiated functions would have the wrong type deco, get it from the 112 1.1 mrg template member instead. */ 113 1.1 mrg if (tdeco == NULL) 114 1.1 mrg { 115 1.1 mrg if (!td || !td->onemember) 116 1.1 mrg return; 117 1.1 mrg 118 1.1 mrg FuncDeclaration *fd = td->onemember->isFuncDeclaration (); 119 1.1 mrg if (fd == NULL) 120 1.1 mrg return; 121 1.1 mrg 122 1.1 mrg OutBuffer buf; 123 1.1 mrg mangleToBuffer (fd->type, &buf); 124 1.1.1.3 mrg tdeco = buf.extractChars (); 125 1.1 mrg } 126 1.1 mrg 127 1.1 mrg /* Matching the type deco may be a bit too strict, as it means that all 128 1.1 mrg function attributes that end up in the signature must be kept aligned 129 1.1 mrg between the compiler and library declaration. */ 130 1.1 mrg if (strcmp (intrinsic_decls[i].deco, tdeco) == 0) 131 1.1 mrg { 132 1.1 mrg intrinsic_code code = intrinsic_decls[i].code; 133 1.1 mrg 134 1.1 mrg if (decl->csym == NULL) 135 1.1 mrg get_symbol_decl (decl); 136 1.1 mrg 137 1.1 mrg /* If there is no function body, then the implementation is always 138 1.1 mrg provided by the compiler. */ 139 1.1 mrg if (!decl->fbody) 140 1.1.1.2 mrg set_decl_built_in_function (decl->csym, BUILT_IN_FRONTEND, code); 141 1.1 mrg 142 1.1 mrg /* Infer whether the intrinsic can be used for CTFE, let the 143 1.1 mrg front-end know that it can be evaluated at compile-time. */ 144 1.1 mrg switch (code) 145 1.1 mrg { 146 1.1 mrg case INTRINSIC_VA_ARG: 147 1.1 mrg case INTRINSIC_C_VA_ARG: 148 1.1 mrg case INTRINSIC_VASTART: 149 1.1 mrg case INTRINSIC_ADDS: 150 1.1.1.3 mrg case INTRINSIC_ADDSL: 151 1.1.1.3 mrg case INTRINSIC_ADDU: 152 1.1.1.3 mrg case INTRINSIC_ADDUL: 153 1.1 mrg case INTRINSIC_SUBS: 154 1.1.1.3 mrg case INTRINSIC_SUBSL: 155 1.1.1.3 mrg case INTRINSIC_SUBU: 156 1.1.1.3 mrg case INTRINSIC_SUBUL: 157 1.1 mrg case INTRINSIC_MULS: 158 1.1.1.3 mrg case INTRINSIC_MULSL: 159 1.1.1.3 mrg case INTRINSIC_MULU: 160 1.1.1.3 mrg case INTRINSIC_MULUI: 161 1.1.1.3 mrg case INTRINSIC_MULUL: 162 1.1 mrg case INTRINSIC_NEGS: 163 1.1.1.3 mrg case INTRINSIC_NEGSL: 164 1.1.1.3 mrg case INTRINSIC_VLOAD8: 165 1.1.1.3 mrg case INTRINSIC_VLOAD16: 166 1.1.1.3 mrg case INTRINSIC_VLOAD32: 167 1.1.1.3 mrg case INTRINSIC_VLOAD64: 168 1.1.1.3 mrg case INTRINSIC_VSTORE8: 169 1.1.1.3 mrg case INTRINSIC_VSTORE16: 170 1.1.1.3 mrg case INTRINSIC_VSTORE32: 171 1.1.1.3 mrg case INTRINSIC_VSTORE64: 172 1.1 mrg break; 173 1.1 mrg 174 1.1 mrg case INTRINSIC_POW: 175 1.1 mrg { 176 1.1 mrg /* Check that this overload of pow() is has an equivalent 177 1.1 mrg built-in function. It could be `int pow(int, int)'. */ 178 1.1 mrg tree rettype = TREE_TYPE (TREE_TYPE (decl->csym)); 179 1.1 mrg if (mathfn_built_in (rettype, BUILT_IN_POW) != NULL_TREE) 180 1.1.1.3 mrg decl->builtin = BUILTIN::gcc; 181 1.1 mrg break; 182 1.1 mrg } 183 1.1 mrg 184 1.1 mrg default: 185 1.1.1.3 mrg decl->builtin = BUILTIN::gcc; 186 1.1 mrg break; 187 1.1 mrg } 188 1.1 mrg 189 1.1 mrg /* The intrinsic was marked as CTFE-only. */ 190 1.1 mrg if (intrinsic_decls[i].ctfeonly) 191 1.1 mrg DECL_BUILT_IN_CTFE (decl->csym) = 1; 192 1.1 mrg 193 1.1 mrg DECL_INTRINSIC_CODE (decl->csym) = code; 194 1.1 mrg break; 195 1.1 mrg } 196 1.1 mrg } 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg /* Construct a function call to the built-in function CODE, N is the number of 200 1.1 mrg arguments, and the `...' parameters are the argument expressions. 201 1.1 mrg The original call expression is held in CALLEXP. */ 202 1.1 mrg 203 1.1 mrg static tree 204 1.1 mrg call_builtin_fn (tree callexp, built_in_function code, int n, ...) 205 1.1 mrg { 206 1.1 mrg tree *argarray = XALLOCAVEC (tree, n); 207 1.1 mrg va_list ap; 208 1.1 mrg 209 1.1 mrg va_start (ap, n); 210 1.1 mrg for (int i = 0; i < n; i++) 211 1.1 mrg argarray[i] = va_arg (ap, tree); 212 1.1 mrg va_end (ap); 213 1.1 mrg 214 1.1 mrg tree exp = build_call_expr_loc_array (EXPR_LOCATION (callexp), 215 1.1 mrg builtin_decl_explicit (code), 216 1.1 mrg n, argarray); 217 1.1 mrg return convert (TREE_TYPE (callexp), fold (exp)); 218 1.1 mrg } 219 1.1 mrg 220 1.1 mrg /* Expand a front-end instrinsic call to bsf(). This takes one argument, 221 1.1 mrg the signature to which can be either: 222 1.1 mrg 223 1.1 mrg int bsf (uint arg); 224 1.1 mrg int bsf (ulong arg); 225 1.1 mrg 226 1.1 mrg This scans all bits in the given argument starting with the first, 227 1.1 mrg returning the bit number of the first bit set. The original call 228 1.1 mrg expression is held in CALLEXP. */ 229 1.1 mrg 230 1.1 mrg static tree 231 1.1 mrg expand_intrinsic_bsf (tree callexp) 232 1.1 mrg { 233 1.1 mrg /* The bsr() intrinsic gets turned into __builtin_ctz(arg). 234 1.1 mrg The return value is supposed to be undefined if arg is zero. */ 235 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0); 236 1.1 mrg int argsize = TYPE_PRECISION (TREE_TYPE (arg)); 237 1.1 mrg 238 1.1 mrg /* Which variant of __builtin_ctz* should we call? */ 239 1.1 mrg built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_CTZ 240 1.1 mrg : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_CTZL 241 1.1 mrg : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_CTZLL 242 1.1 mrg : END_BUILTINS; 243 1.1 mrg 244 1.1 mrg gcc_assert (code != END_BUILTINS); 245 1.1 mrg 246 1.1 mrg return call_builtin_fn (callexp, code, 1, arg); 247 1.1 mrg } 248 1.1 mrg 249 1.1 mrg /* Expand a front-end instrinsic call to bsr(). This takes one argument, 250 1.1 mrg the signature to which can be either: 251 1.1 mrg 252 1.1 mrg int bsr (uint arg); 253 1.1 mrg int bsr (ulong arg); 254 1.1 mrg 255 1.1 mrg This scans all bits in the given argument from the most significant bit 256 1.1 mrg to the least significant, returning the bit number of the first bit set. 257 1.1 mrg The original call expression is held in CALLEXP. */ 258 1.1 mrg 259 1.1 mrg static tree 260 1.1 mrg expand_intrinsic_bsr (tree callexp) 261 1.1 mrg { 262 1.1 mrg /* The bsr() intrinsic gets turned into (size - 1) - __builtin_clz(arg). 263 1.1 mrg The return value is supposed to be undefined if arg is zero. */ 264 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0); 265 1.1 mrg tree type = TREE_TYPE (arg); 266 1.1 mrg int argsize = TYPE_PRECISION (type); 267 1.1 mrg 268 1.1 mrg /* Which variant of __builtin_clz* should we call? */ 269 1.1 mrg built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_CLZ 270 1.1 mrg : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_CLZL 271 1.1 mrg : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_CLZLL 272 1.1 mrg : END_BUILTINS; 273 1.1 mrg 274 1.1 mrg gcc_assert (code != END_BUILTINS); 275 1.1 mrg 276 1.1 mrg tree result = call_builtin_fn (callexp, code, 1, arg); 277 1.1 mrg 278 1.1 mrg /* Handle int -> long conversions. */ 279 1.1 mrg if (TREE_TYPE (result) != type) 280 1.1 mrg result = fold_convert (type, result); 281 1.1 mrg 282 1.1 mrg result = fold_build2 (MINUS_EXPR, type, 283 1.1 mrg build_integer_cst (argsize - 1, type), result); 284 1.1 mrg return fold_convert (TREE_TYPE (callexp), result); 285 1.1 mrg } 286 1.1 mrg 287 1.1 mrg /* Expand a front-end intrinsic call to INTRINSIC, which is either a call to 288 1.1 mrg bt(), btc(), btr(), or bts(). These intrinsics expect to take two arguments, 289 1.1 mrg the signature to which is: 290 1.1 mrg 291 1.1 mrg int bt (size_t* ptr, size_t bitnum); 292 1.1 mrg 293 1.1 mrg All intrinsics test if a bit is set and return the result of that condition. 294 1.1 mrg Variants of `bt' will then update that bit. `btc' compliments the bit, `bts' 295 1.1 mrg sets the bit, and `btr' resets the bit. The original call expression is 296 1.1 mrg held in CALLEXP. */ 297 1.1 mrg 298 1.1 mrg static tree 299 1.1 mrg expand_intrinsic_bt (intrinsic_code intrinsic, tree callexp) 300 1.1 mrg { 301 1.1 mrg tree ptr = CALL_EXPR_ARG (callexp, 0); 302 1.1 mrg tree bitnum = CALL_EXPR_ARG (callexp, 1); 303 1.1 mrg tree type = TREE_TYPE (TREE_TYPE (ptr)); 304 1.1 mrg 305 1.1 mrg /* size_t bitsize = sizeof(*ptr) * BITS_PER_UNIT; */ 306 1.1.1.3 mrg tree bitsize = fold_convert (type, TYPE_SIZE (TREE_TYPE (ptr))); 307 1.1 mrg 308 1.1 mrg /* ptr[bitnum / bitsize] */ 309 1.1 mrg ptr = build_array_index (ptr, fold_build2 (TRUNC_DIV_EXPR, type, 310 1.1 mrg bitnum, bitsize)); 311 1.1 mrg ptr = indirect_ref (type, ptr); 312 1.1 mrg 313 1.1 mrg /* mask = 1 << (bitnum % bitsize); */ 314 1.1 mrg bitnum = fold_build2 (TRUNC_MOD_EXPR, type, bitnum, bitsize); 315 1.1.1.3 mrg bitnum = fold_build2 (LSHIFT_EXPR, type, build_one_cst (type), bitnum); 316 1.1 mrg 317 1.1 mrg /* cond = ptr[bitnum / size] & mask; */ 318 1.1 mrg tree cond = fold_build2 (BIT_AND_EXPR, type, ptr, bitnum); 319 1.1 mrg 320 1.1 mrg /* cond ? -1 : 0; */ 321 1.1 mrg cond = build_condition (TREE_TYPE (callexp), d_truthvalue_conversion (cond), 322 1.1.1.3 mrg build_minus_one_cst (TREE_TYPE (callexp)), 323 1.1.1.3 mrg build_zero_cst (TREE_TYPE (callexp))); 324 1.1 mrg 325 1.1 mrg /* Update the bit as needed, only testing the bit for bt(). */ 326 1.1.1.3 mrg tree_code code; 327 1.1 mrg 328 1.1.1.3 mrg switch (intrinsic) 329 1.1.1.3 mrg { 330 1.1.1.3 mrg case INTRINSIC_BT: 331 1.1.1.3 mrg case INTRINSIC_BT64: 332 1.1.1.3 mrg return cond; 333 1.1 mrg 334 1.1.1.3 mrg case INTRINSIC_BTC: 335 1.1.1.3 mrg case INTRINSIC_BTC64: 336 1.1.1.3 mrg code = BIT_XOR_EXPR; 337 1.1.1.3 mrg break; 338 1.1.1.3 mrg 339 1.1.1.3 mrg case INTRINSIC_BTR: 340 1.1.1.3 mrg case INTRINSIC_BTR64: 341 1.1.1.3 mrg bitnum = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (bitnum), bitnum); 342 1.1.1.3 mrg code = BIT_AND_EXPR; 343 1.1.1.3 mrg break; 344 1.1.1.3 mrg 345 1.1.1.3 mrg case INTRINSIC_BTS: 346 1.1.1.3 mrg case INTRINSIC_BTS64: 347 1.1.1.3 mrg code = BIT_IOR_EXPR; 348 1.1.1.3 mrg break; 349 1.1 mrg 350 1.1.1.3 mrg default: 351 1.1.1.3 mrg gcc_unreachable (); 352 1.1.1.3 mrg } 353 1.1.1.3 mrg 354 1.1.1.3 mrg /* ptr[bitnum / size] op= mask; */ 355 1.1 mrg ptr = modify_expr (ptr, fold_build2 (code, TREE_TYPE (ptr), ptr, bitnum)); 356 1.1 mrg 357 1.1 mrg /* Store the condition result in a temporary, and return expressions in 358 1.1 mrg correct order of evaluation. */ 359 1.1 mrg tree tmp = build_local_temp (TREE_TYPE (callexp)); 360 1.1 mrg cond = modify_expr (tmp, cond); 361 1.1 mrg 362 1.1 mrg return compound_expr (cond, compound_expr (ptr, tmp)); 363 1.1 mrg } 364 1.1 mrg 365 1.1 mrg /* Expand a front-end intrinsic call to popcnt(). This takes one argument, the 366 1.1 mrg signature to which can be either: 367 1.1 mrg 368 1.1 mrg int popcnt (uint arg); 369 1.1 mrg int popcnt (ulong arg); 370 1.1 mrg 371 1.1 mrg Calculates the number of set bits in an integer. The original call 372 1.1 mrg expression is held in CALLEXP. */ 373 1.1 mrg 374 1.1 mrg static tree 375 1.1 mrg expand_intrinsic_popcnt (tree callexp) 376 1.1 mrg { 377 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0); 378 1.1 mrg int argsize = TYPE_PRECISION (TREE_TYPE (arg)); 379 1.1 mrg 380 1.1 mrg /* Which variant of __builtin_popcount* should we call? */ 381 1.1 mrg built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_POPCOUNT 382 1.1 mrg : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_POPCOUNTL 383 1.1 mrg : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_POPCOUNTLL 384 1.1 mrg : END_BUILTINS; 385 1.1 mrg 386 1.1 mrg gcc_assert (code != END_BUILTINS); 387 1.1 mrg 388 1.1 mrg return call_builtin_fn (callexp, code, 1, arg); 389 1.1 mrg } 390 1.1 mrg 391 1.1 mrg /* Expand a front-end intrinsic call to INTRINSIC, which is either a call to 392 1.1.1.3 mrg rol() or ror(). These intrinsics expect to take one or two arguments, 393 1.1 mrg the signature to which can be either: 394 1.1 mrg 395 1.1.1.3 mrg T rol(T) (const T value, const uint count); 396 1.1.1.3 mrg T rol(uint count, T) (const T value); 397 1.1.1.3 mrg T ror(T) (const T value, const uint count); 398 1.1.1.3 mrg T ror(uint count, T) (const T value); 399 1.1 mrg 400 1.1.1.3 mrg This bitwise rotates VALUE left or right by COUNT bit positions. */ 401 1.1 mrg 402 1.1 mrg static tree 403 1.1.1.3 mrg expand_intrinsic_rotate (intrinsic_code intrinsic, tree callexp) 404 1.1 mrg { 405 1.1.1.3 mrg tree type = TREE_TYPE (callexp); 406 1.1.1.3 mrg tree value = CALL_EXPR_ARG (callexp, 0); 407 1.1.1.3 mrg tree count; 408 1.1.1.3 mrg tree_code code; 409 1.1.1.3 mrg 410 1.1.1.3 mrg /* Get the equivalent tree code for the intrinsic. */ 411 1.1.1.3 mrg if (intrinsic == INTRINSIC_ROL || intrinsic == INTRINSIC_ROL_TIARG) 412 1.1.1.3 mrg code = LROTATE_EXPR; 413 1.1.1.3 mrg else if (intrinsic == INTRINSIC_ROR || intrinsic == INTRINSIC_ROR_TIARG) 414 1.1.1.3 mrg code = RROTATE_EXPR; 415 1.1.1.3 mrg else 416 1.1.1.3 mrg gcc_unreachable (); 417 1.1 mrg 418 1.1.1.3 mrg /* Get the COUNT parameter. Either from the call expression arguments or the 419 1.1.1.3 mrg template instantiation arguments. */ 420 1.1.1.3 mrg if (intrinsic == INTRINSIC_ROL || intrinsic == INTRINSIC_ROR) 421 1.1.1.3 mrg count = CALL_EXPR_ARG (callexp, 1); 422 1.1.1.3 mrg else 423 1.1.1.3 mrg { 424 1.1.1.3 mrg tree callee = CALL_EXPR_FN (callexp); 425 1.1 mrg 426 1.1.1.3 mrg if (TREE_CODE (callee) == ADDR_EXPR) 427 1.1.1.3 mrg callee = TREE_OPERAND (callee, 0); 428 1.1.1.3 mrg 429 1.1.1.3 mrg /* Retrieve from the encoded template instantation. */ 430 1.1.1.3 mrg TemplateInstance *ti = DECL_LANG_FRONTEND (callee)->isInstantiated (); 431 1.1.1.3 mrg gcc_assert (ti && ti->tiargs && ti->tiargs->length == 2); 432 1.1.1.3 mrg 433 1.1.1.3 mrg Expression *e = isExpression ((*ti->tiargs)[0]); 434 1.1.1.3 mrg gcc_assert (e && e->op == EXP::int64); 435 1.1.1.3 mrg count = build_expr (e, true); 436 1.1.1.3 mrg } 437 1.1.1.3 mrg 438 1.1.1.3 mrg return fold_build2 (code, type, value, count); 439 1.1 mrg } 440 1.1 mrg 441 1.1 mrg /* Expand a front-end intrinsic call to copysign(). This takes two arguments, 442 1.1 mrg the signature to which can be either: 443 1.1 mrg 444 1.1 mrg float copysign (T to, float from); 445 1.1 mrg double copysign (T to, double from); 446 1.1 mrg real copysign (T to, real from); 447 1.1 mrg 448 1.1 mrg This computes a value composed of TO with the sign bit of FROM. The original 449 1.1 mrg call expression is held in CALLEXP. */ 450 1.1 mrg 451 1.1 mrg static tree 452 1.1 mrg expand_intrinsic_copysign (tree callexp) 453 1.1 mrg { 454 1.1 mrg tree to = CALL_EXPR_ARG (callexp, 0); 455 1.1 mrg tree from = CALL_EXPR_ARG (callexp, 1); 456 1.1 mrg tree type = TREE_TYPE (to); 457 1.1 mrg 458 1.1 mrg /* Convert parameters to the same type. Prefer the first parameter unless it 459 1.1 mrg is an integral type. */ 460 1.1 mrg if (INTEGRAL_TYPE_P (type)) 461 1.1 mrg { 462 1.1 mrg to = fold_convert (TREE_TYPE (from), to); 463 1.1 mrg type = TREE_TYPE (to); 464 1.1 mrg } 465 1.1 mrg else 466 1.1 mrg from = fold_convert (type, from); 467 1.1 mrg 468 1.1 mrg /* Which variant of __builtin_copysign* should we call? */ 469 1.1.1.2 mrg built_in_function code = (type == float_type_node) ? BUILT_IN_COPYSIGNF 470 1.1.1.2 mrg : (type == double_type_node) ? BUILT_IN_COPYSIGN 471 1.1.1.2 mrg : (type == long_double_type_node) ? BUILT_IN_COPYSIGNL 472 1.1.1.2 mrg : END_BUILTINS; 473 1.1 mrg 474 1.1.1.2 mrg gcc_assert (code != END_BUILTINS); 475 1.1.1.2 mrg 476 1.1.1.2 mrg return call_builtin_fn (callexp, code, 2, to, from); 477 1.1 mrg } 478 1.1 mrg 479 1.1 mrg /* Expand a front-end intrinsic call to pow(). This takes two arguments, the 480 1.1 mrg signature to which can be either: 481 1.1 mrg 482 1.1 mrg float pow (float base, T exponent); 483 1.1 mrg double pow (double base, T exponent); 484 1.1 mrg real pow (real base, T exponent); 485 1.1 mrg 486 1.1 mrg This computes the value of BASE raised to the power of EXPONENT. 487 1.1 mrg The original call expression is held in CALLEXP. */ 488 1.1 mrg 489 1.1 mrg static tree 490 1.1 mrg expand_intrinsic_pow (tree callexp) 491 1.1 mrg { 492 1.1 mrg tree base = CALL_EXPR_ARG (callexp, 0); 493 1.1 mrg tree exponent = CALL_EXPR_ARG (callexp, 1); 494 1.1 mrg tree exptype = TREE_TYPE (exponent); 495 1.1 mrg 496 1.1 mrg /* Which variant of __builtin_pow* should we call? */ 497 1.1 mrg built_in_function code = SCALAR_FLOAT_TYPE_P (exptype) ? BUILT_IN_POW 498 1.1 mrg : INTEGRAL_TYPE_P (exptype) ? BUILT_IN_POWI 499 1.1 mrg : END_BUILTINS; 500 1.1 mrg gcc_assert (code != END_BUILTINS); 501 1.1 mrg 502 1.1 mrg tree builtin = mathfn_built_in (TREE_TYPE (base), code); 503 1.1 mrg gcc_assert (builtin != NULL_TREE); 504 1.1 mrg 505 1.1 mrg return call_builtin_fn (callexp, DECL_FUNCTION_CODE (builtin), 2, 506 1.1 mrg base, exponent); 507 1.1 mrg } 508 1.1 mrg 509 1.1.1.2 mrg /* Expand a front-end intrinsic call to toPrec(). This takes one argument, the 510 1.1.1.2 mrg signature to which can be either: 511 1.1.1.2 mrg 512 1.1.1.2 mrg T toPrec(T)(float f); 513 1.1.1.2 mrg T toPrec(T)(double f); 514 1.1.1.2 mrg T toPrec(T)(real f); 515 1.1.1.2 mrg 516 1.1.1.2 mrg This rounds the argument F to the precision of the specified floating 517 1.1.1.2 mrg point type T. The original call expression is held in CALLEXP. */ 518 1.1.1.2 mrg 519 1.1.1.2 mrg static tree 520 1.1.1.2 mrg expand_intrinsic_toprec (tree callexp) 521 1.1.1.2 mrg { 522 1.1.1.2 mrg tree f = CALL_EXPR_ARG (callexp, 0); 523 1.1.1.2 mrg tree type = TREE_TYPE (callexp); 524 1.1.1.2 mrg 525 1.1.1.2 mrg return convert (type, f); 526 1.1.1.2 mrg } 527 1.1.1.2 mrg 528 1.1 mrg /* Expand a front-end intrinsic call to va_arg(). This takes either one or two 529 1.1 mrg arguments, the signature to which can be either: 530 1.1 mrg 531 1.1 mrg T va_arg(T) (ref va_list ap); 532 1.1 mrg void va_arg(T) (va_list ap, ref T parmn); 533 1.1 mrg 534 1.1 mrg This retrieves the next variadic parameter that is type T from the given 535 1.1 mrg va_list. If also given, store the value into parmn, otherwise return it. 536 1.1 mrg The original call expression is held in CALLEXP. */ 537 1.1 mrg 538 1.1 mrg static tree 539 1.1 mrg expand_intrinsic_vaarg (tree callexp) 540 1.1 mrg { 541 1.1 mrg tree ap = CALL_EXPR_ARG (callexp, 0); 542 1.1 mrg tree parmn = NULL_TREE; 543 1.1 mrg tree type; 544 1.1 mrg 545 1.1 mrg STRIP_NOPS (ap); 546 1.1 mrg 547 1.1 mrg if (call_expr_nargs (callexp) == 1) 548 1.1 mrg type = TREE_TYPE (callexp); 549 1.1 mrg else 550 1.1 mrg { 551 1.1 mrg parmn = CALL_EXPR_ARG (callexp, 1); 552 1.1 mrg STRIP_NOPS (parmn); 553 1.1.1.2 mrg 554 1.1.1.2 mrg /* The `ref' argument to va_arg is either an address or reference, 555 1.1.1.2 mrg get the value of it. */ 556 1.1.1.2 mrg if (TREE_CODE (parmn) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (parmn))) 557 1.1.1.2 mrg parmn = build_deref (parmn); 558 1.1.1.2 mrg else 559 1.1.1.2 mrg { 560 1.1.1.2 mrg gcc_assert (TREE_CODE (parmn) == ADDR_EXPR); 561 1.1.1.2 mrg parmn = TREE_OPERAND (parmn, 0); 562 1.1.1.2 mrg } 563 1.1.1.2 mrg 564 1.1 mrg type = TREE_TYPE (parmn); 565 1.1 mrg } 566 1.1 mrg 567 1.1 mrg /* (T) VA_ARG_EXP<ap>; */ 568 1.1.1.3 mrg tree exp = build1_loc (EXPR_LOCATION (callexp), VA_ARG_EXPR, type, ap); 569 1.1 mrg 570 1.1 mrg /* parmn = (T) VA_ARG_EXP<ap>; */ 571 1.1 mrg if (parmn != NULL_TREE) 572 1.1 mrg exp = modify_expr (parmn, exp); 573 1.1 mrg 574 1.1 mrg return exp; 575 1.1 mrg } 576 1.1 mrg 577 1.1 mrg /* Expand a front-end intrinsic call to va_start(), which takes two arguments, 578 1.1 mrg the signature to which is: 579 1.1 mrg 580 1.1 mrg void va_start(T) (out va_list ap, ref T parmn); 581 1.1 mrg 582 1.1 mrg This initializes the va_list type, where parmn should be the last named 583 1.1 mrg parameter. The original call expression is held in CALLEXP. */ 584 1.1 mrg 585 1.1 mrg static tree 586 1.1 mrg expand_intrinsic_vastart (tree callexp) 587 1.1 mrg { 588 1.1 mrg tree ap = CALL_EXPR_ARG (callexp, 0); 589 1.1 mrg tree parmn = CALL_EXPR_ARG (callexp, 1); 590 1.1 mrg 591 1.1 mrg STRIP_NOPS (ap); 592 1.1 mrg STRIP_NOPS (parmn); 593 1.1 mrg 594 1.1 mrg /* The va_list argument should already have its address taken. The second 595 1.1 mrg argument, however, is inout and that needs to be fixed to prevent a 596 1.1 mrg warning. Could be casting, so need to check type too? */ 597 1.1.1.2 mrg gcc_assert (TREE_CODE (ap) == ADDR_EXPR 598 1.1.1.2 mrg || (TREE_CODE (ap) == PARM_DECL 599 1.1.1.2 mrg && POINTER_TYPE_P (TREE_TYPE (ap)))); 600 1.1 mrg 601 1.1 mrg /* Assuming nobody tries to change the return type. */ 602 1.1.1.2 mrg if (TREE_CODE (parmn) != PARM_DECL) 603 1.1.1.2 mrg { 604 1.1.1.2 mrg gcc_assert (TREE_CODE (parmn) == ADDR_EXPR); 605 1.1.1.2 mrg parmn = TREE_OPERAND (parmn, 0); 606 1.1.1.2 mrg } 607 1.1 mrg 608 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_VA_START, 2, ap, parmn); 609 1.1 mrg } 610 1.1 mrg 611 1.1 mrg /* Expand a front-end instrinsic call to INTRINSIC, which is either a call to 612 1.1 mrg adds(), addu(), subs(), subu(), negs(), muls(), or mulu(). These intrinsics 613 1.1 mrg expect to take two or three arguments, the signature to which can be either: 614 1.1 mrg 615 1.1 mrg int adds (int x, int y, ref bool overflow); 616 1.1 mrg long adds (long x, long y, ref bool overflow); 617 1.1 mrg int negs (int x, ref bool overflow); 618 1.1 mrg long negs (long x, ref bool overflow); 619 1.1 mrg 620 1.1 mrg This performs an operation on two signed or unsigned integers, checking for 621 1.1 mrg overflow. The overflow is sticky, meaning that a sequence of operations 622 1.1 mrg can be done and overflow need only be checked at the end. The original call 623 1.1 mrg expression is held in CALLEXP. */ 624 1.1 mrg 625 1.1 mrg static tree 626 1.1 mrg expand_intrinsic_checkedint (intrinsic_code intrinsic, tree callexp) 627 1.1 mrg { 628 1.1 mrg tree type = TREE_TYPE (callexp); 629 1.1 mrg tree x; 630 1.1 mrg tree y; 631 1.1 mrg tree overflow; 632 1.1.1.3 mrg internal_fn icode; 633 1.1 mrg 634 1.1.1.3 mrg /* Which variant of *_OVERFLOW should we generate? */ 635 1.1.1.3 mrg switch (intrinsic) 636 1.1 mrg { 637 1.1.1.3 mrg case INTRINSIC_ADDS: 638 1.1.1.3 mrg case INTRINSIC_ADDSL: 639 1.1.1.3 mrg case INTRINSIC_ADDU: 640 1.1.1.3 mrg case INTRINSIC_ADDUL: 641 1.1 mrg x = CALL_EXPR_ARG (callexp, 0); 642 1.1 mrg y = CALL_EXPR_ARG (callexp, 1); 643 1.1 mrg overflow = CALL_EXPR_ARG (callexp, 2); 644 1.1.1.3 mrg icode = IFN_ADD_OVERFLOW; 645 1.1.1.3 mrg break; 646 1.1 mrg 647 1.1.1.3 mrg case INTRINSIC_SUBS: 648 1.1.1.3 mrg case INTRINSIC_SUBSL: 649 1.1.1.3 mrg case INTRINSIC_SUBU: 650 1.1.1.3 mrg case INTRINSIC_SUBUL: 651 1.1.1.3 mrg x = CALL_EXPR_ARG (callexp, 0); 652 1.1.1.3 mrg y = CALL_EXPR_ARG (callexp, 1); 653 1.1.1.3 mrg overflow = CALL_EXPR_ARG (callexp, 2); 654 1.1.1.3 mrg icode = IFN_SUB_OVERFLOW; 655 1.1.1.3 mrg break; 656 1.1.1.3 mrg 657 1.1.1.3 mrg case INTRINSIC_MULS: 658 1.1.1.3 mrg case INTRINSIC_MULSL: 659 1.1.1.3 mrg case INTRINSIC_MULU: 660 1.1.1.3 mrg case INTRINSIC_MULUI: 661 1.1.1.3 mrg case INTRINSIC_MULUL: 662 1.1.1.3 mrg x = CALL_EXPR_ARG (callexp, 0); 663 1.1.1.3 mrg y = CALL_EXPR_ARG (callexp, 1); 664 1.1.1.3 mrg overflow = CALL_EXPR_ARG (callexp, 2); 665 1.1.1.3 mrg icode = IFN_MUL_OVERFLOW; 666 1.1.1.3 mrg break; 667 1.1.1.3 mrg 668 1.1.1.3 mrg case INTRINSIC_NEGS: 669 1.1.1.3 mrg case INTRINSIC_NEGSL: 670 1.1.1.3 mrg /* The negs() intrinsic gets turned into SUB_OVERFLOW (0, y). */ 671 1.1.1.3 mrg x = fold_convert (type, integer_zero_node); 672 1.1.1.3 mrg y = CALL_EXPR_ARG (callexp, 0); 673 1.1.1.3 mrg overflow = CALL_EXPR_ARG (callexp, 1); 674 1.1.1.3 mrg icode = IFN_SUB_OVERFLOW; 675 1.1.1.3 mrg break; 676 1.1.1.3 mrg 677 1.1.1.3 mrg default: 678 1.1.1.3 mrg gcc_unreachable (); 679 1.1.1.3 mrg } 680 1.1 mrg 681 1.1 mrg tree result 682 1.1 mrg = build_call_expr_internal_loc (EXPR_LOCATION (callexp), icode, 683 1.1 mrg build_complex_type (type), 2, x, y); 684 1.1 mrg 685 1.1 mrg STRIP_NOPS (overflow); 686 1.1 mrg overflow = build_deref (overflow); 687 1.1 mrg 688 1.1 mrg /* Assign returned result to overflow parameter, however if overflow is 689 1.1 mrg already true, maintain its value. */ 690 1.1 mrg type = TREE_TYPE (overflow); 691 1.1 mrg result = save_expr (result); 692 1.1 mrg 693 1.1 mrg tree exp = fold_build2 (BIT_IOR_EXPR, type, overflow, 694 1.1 mrg fold_convert (type, imaginary_part (result))); 695 1.1 mrg exp = modify_expr (overflow, exp); 696 1.1 mrg 697 1.1 mrg /* Return the value of result. */ 698 1.1 mrg return compound_expr (exp, real_part (result)); 699 1.1 mrg } 700 1.1 mrg 701 1.1 mrg /* Expand a front-end instrinsic call to volatileLoad(). This takes one 702 1.1 mrg argument, the signature to which can be either: 703 1.1 mrg 704 1.1 mrg ubyte volatileLoad (ubyte* ptr); 705 1.1 mrg ushort volatileLoad (ushort* ptr); 706 1.1 mrg uint volatileLoad (uint* ptr); 707 1.1 mrg ulong volatileLoad (ulong* ptr); 708 1.1 mrg 709 1.1 mrg This reads a value from the memory location indicated by ptr. Calls to 710 1.1 mrg them are be guaranteed to not be removed (such as during DCE) or reordered 711 1.1 mrg in the same thread. The original call expression is held in CALLEXP. */ 712 1.1 mrg 713 1.1 mrg static tree 714 1.1 mrg expand_volatile_load (tree callexp) 715 1.1 mrg { 716 1.1 mrg tree ptr = CALL_EXPR_ARG (callexp, 0); 717 1.1 mrg tree ptrtype = TREE_TYPE (ptr); 718 1.1 mrg gcc_assert (POINTER_TYPE_P (ptrtype)); 719 1.1 mrg 720 1.1 mrg /* (T) *(volatile T *) ptr; */ 721 1.1 mrg tree type = build_qualified_type (TREE_TYPE (ptrtype), TYPE_QUAL_VOLATILE); 722 1.1 mrg tree result = indirect_ref (type, ptr); 723 1.1 mrg TREE_THIS_VOLATILE (result) = 1; 724 1.1.1.3 mrg TREE_SIDE_EFFECTS (result) = 1; 725 1.1 mrg 726 1.1 mrg return result; 727 1.1 mrg } 728 1.1 mrg 729 1.1 mrg /* Expand a front-end instrinsic call to volatileStore(). This takes two 730 1.1 mrg arguments, the signature to which can be either: 731 1.1 mrg 732 1.1 mrg void volatileStore (ubyte* ptr, ubyte value); 733 1.1 mrg void volatileStore (ushort* ptr, ushort value); 734 1.1 mrg void volatileStore (uint* ptr, uint value); 735 1.1 mrg void volatileStore (ulong* ptr, ulong value); 736 1.1 mrg 737 1.1 mrg This writes a value to the memory location indicated by ptr. Calls to 738 1.1 mrg them are be guaranteed to not be removed (such as during DCE) or reordered 739 1.1 mrg in the same thread. The original call expression is held in CALLEXP. */ 740 1.1 mrg 741 1.1 mrg static tree 742 1.1 mrg expand_volatile_store (tree callexp) 743 1.1 mrg { 744 1.1 mrg tree ptr = CALL_EXPR_ARG (callexp, 0); 745 1.1 mrg tree ptrtype = TREE_TYPE (ptr); 746 1.1 mrg gcc_assert (POINTER_TYPE_P (ptrtype)); 747 1.1 mrg 748 1.1 mrg /* (T) *(volatile T *) ptr; */ 749 1.1 mrg tree type = build_qualified_type (TREE_TYPE (ptrtype), TYPE_QUAL_VOLATILE); 750 1.1 mrg tree result = indirect_ref (type, ptr); 751 1.1 mrg TREE_THIS_VOLATILE (result) = 1; 752 1.1.1.3 mrg TREE_SIDE_EFFECTS (result) = 1; 753 1.1 mrg 754 1.1 mrg /* (*(volatile T *) ptr) = value; */ 755 1.1 mrg tree value = CALL_EXPR_ARG (callexp, 1); 756 1.1 mrg return modify_expr (result, value); 757 1.1 mrg } 758 1.1 mrg 759 1.1 mrg /* If CALLEXP is for an intrinsic , expand and return inlined compiler 760 1.1 mrg generated instructions. Most map directly to GCC builtins, others 761 1.1 mrg require a little extra work around them. */ 762 1.1 mrg 763 1.1 mrg tree 764 1.1 mrg maybe_expand_intrinsic (tree callexp) 765 1.1 mrg { 766 1.1 mrg tree callee = CALL_EXPR_FN (callexp); 767 1.1 mrg 768 1.1 mrg if (TREE_CODE (callee) == ADDR_EXPR) 769 1.1 mrg callee = TREE_OPERAND (callee, 0); 770 1.1 mrg 771 1.1 mrg if (TREE_CODE (callee) != FUNCTION_DECL) 772 1.1 mrg return callexp; 773 1.1 mrg 774 1.1 mrg /* Don't expand CTFE-only intrinsics outside of semantic processing. */ 775 1.1 mrg if (DECL_BUILT_IN_CTFE (callee) && !doing_semantic_analysis_p) 776 1.1 mrg return callexp; 777 1.1 mrg 778 1.1 mrg intrinsic_code intrinsic = DECL_INTRINSIC_CODE (callee); 779 1.1 mrg built_in_function code; 780 1.1 mrg 781 1.1 mrg switch (intrinsic) 782 1.1 mrg { 783 1.1 mrg case INTRINSIC_NONE: 784 1.1 mrg return callexp; 785 1.1 mrg 786 1.1 mrg case INTRINSIC_BSF: 787 1.1.1.3 mrg case INTRINSIC_BSF64: 788 1.1 mrg return expand_intrinsic_bsf (callexp); 789 1.1 mrg 790 1.1 mrg case INTRINSIC_BSR: 791 1.1.1.3 mrg case INTRINSIC_BSR64: 792 1.1 mrg return expand_intrinsic_bsr (callexp); 793 1.1 mrg 794 1.1 mrg case INTRINSIC_BT: 795 1.1.1.3 mrg case INTRINSIC_BT64: 796 1.1 mrg case INTRINSIC_BTC: 797 1.1.1.3 mrg case INTRINSIC_BTC64: 798 1.1 mrg case INTRINSIC_BTR: 799 1.1.1.3 mrg case INTRINSIC_BTR64: 800 1.1 mrg case INTRINSIC_BTS: 801 1.1.1.3 mrg case INTRINSIC_BTS64: 802 1.1 mrg return expand_intrinsic_bt (intrinsic, callexp); 803 1.1 mrg 804 1.1.1.3 mrg case INTRINSIC_POPCNT32: 805 1.1.1.3 mrg case INTRINSIC_POPCNT64: 806 1.1 mrg return expand_intrinsic_popcnt (callexp); 807 1.1 mrg 808 1.1.1.3 mrg case INTRINSIC_ROL: 809 1.1.1.3 mrg case INTRINSIC_ROL_TIARG: 810 1.1.1.3 mrg case INTRINSIC_ROR: 811 1.1.1.3 mrg case INTRINSIC_ROR_TIARG: 812 1.1.1.3 mrg return expand_intrinsic_rotate (intrinsic, callexp); 813 1.1.1.3 mrg 814 1.1.1.3 mrg case INTRINSIC_BSWAP16: 815 1.1.1.3 mrg case INTRINSIC_BSWAP32: 816 1.1.1.3 mrg case INTRINSIC_BSWAP64: 817 1.1.1.3 mrg case INTRINSIC_CEIL: 818 1.1.1.3 mrg case INTRINSIC_CEILF: 819 1.1.1.3 mrg case INTRINSIC_CEILL: 820 1.1 mrg case INTRINSIC_COS: 821 1.1.1.3 mrg case INTRINSIC_COSF: 822 1.1.1.3 mrg case INTRINSIC_COSL: 823 1.1 mrg case INTRINSIC_EXP: 824 1.1 mrg case INTRINSIC_EXP2: 825 1.1.1.3 mrg case INTRINSIC_EXPM1: 826 1.1.1.3 mrg case INTRINSIC_FABS: 827 1.1.1.3 mrg case INTRINSIC_FABSF: 828 1.1.1.3 mrg case INTRINSIC_FABSL: 829 1.1.1.3 mrg case INTRINSIC_FLOOR: 830 1.1.1.3 mrg case INTRINSIC_FLOORF: 831 1.1.1.3 mrg case INTRINSIC_FLOORL: 832 1.1.1.3 mrg case INTRINSIC_ISFINITE: 833 1.1.1.3 mrg case INTRINSIC_ISINFINITY: 834 1.1.1.3 mrg case INTRINSIC_ISNAN: 835 1.1 mrg case INTRINSIC_LOG: 836 1.1 mrg case INTRINSIC_LOG10: 837 1.1.1.3 mrg case INTRINSIC_LOG2: 838 1.1.1.3 mrg case INTRINSIC_RINT: 839 1.1.1.3 mrg case INTRINSIC_RINTF: 840 1.1.1.3 mrg case INTRINSIC_RINTL: 841 1.1.1.3 mrg case INTRINSIC_RNDTOL: 842 1.1.1.3 mrg case INTRINSIC_RNDTOLF: 843 1.1.1.3 mrg case INTRINSIC_RNDTOLL: 844 1.1 mrg case INTRINSIC_ROUND: 845 1.1.1.3 mrg case INTRINSIC_SIN: 846 1.1.1.3 mrg case INTRINSIC_SINF: 847 1.1.1.3 mrg case INTRINSIC_SINL: 848 1.1.1.3 mrg case INTRINSIC_SQRT: 849 1.1.1.3 mrg case INTRINSIC_SQRTF: 850 1.1.1.3 mrg case INTRINSIC_SQRTL: 851 1.1.1.3 mrg case INTRINSIC_TAN: 852 1.1 mrg case INTRINSIC_TRUNC: 853 1.1.1.3 mrg code = intrinsic_decls[intrinsic].built_in; 854 1.1.1.3 mrg gcc_assert (code != BUILT_IN_NONE); 855 1.1.1.3 mrg return call_builtin_fn (callexp, code, 1, 856 1.1 mrg CALL_EXPR_ARG (callexp, 0)); 857 1.1 mrg 858 1.1.1.3 mrg case INTRINSIC_FMAX: 859 1.1 mrg case INTRINSIC_FMIN: 860 1.1.1.3 mrg case INTRINSIC_LDEXP: 861 1.1.1.3 mrg case INTRINSIC_LDEXPF: 862 1.1.1.3 mrg case INTRINSIC_LDEXPL: 863 1.1.1.3 mrg code = intrinsic_decls[intrinsic].built_in; 864 1.1.1.3 mrg gcc_assert (code != BUILT_IN_NONE); 865 1.1.1.3 mrg return call_builtin_fn (callexp, code, 2, 866 1.1 mrg CALL_EXPR_ARG (callexp, 0), 867 1.1 mrg CALL_EXPR_ARG (callexp, 1)); 868 1.1 mrg 869 1.1.1.3 mrg case INTRINSIC_FMA: 870 1.1.1.3 mrg code = intrinsic_decls[intrinsic].built_in; 871 1.1.1.3 mrg gcc_assert (code != BUILT_IN_NONE); 872 1.1.1.3 mrg return call_builtin_fn (callexp, code, 3, 873 1.1 mrg CALL_EXPR_ARG (callexp, 0), 874 1.1.1.3 mrg CALL_EXPR_ARG (callexp, 1), 875 1.1.1.3 mrg CALL_EXPR_ARG (callexp, 2)); 876 1.1 mrg 877 1.1 mrg case INTRINSIC_COPYSIGN: 878 1.1.1.3 mrg case INTRINSIC_COPYSIGNI: 879 1.1 mrg return expand_intrinsic_copysign (callexp); 880 1.1 mrg 881 1.1 mrg case INTRINSIC_POW: 882 1.1 mrg return expand_intrinsic_pow (callexp); 883 1.1 mrg 884 1.1.1.2 mrg case INTRINSIC_TOPREC: 885 1.1.1.3 mrg case INTRINSIC_TOPRECF: 886 1.1.1.3 mrg case INTRINSIC_TOPRECL: 887 1.1.1.2 mrg return expand_intrinsic_toprec (callexp); 888 1.1.1.2 mrg 889 1.1 mrg case INTRINSIC_VA_ARG: 890 1.1 mrg case INTRINSIC_C_VA_ARG: 891 1.1 mrg return expand_intrinsic_vaarg (callexp); 892 1.1 mrg 893 1.1 mrg case INTRINSIC_VASTART: 894 1.1 mrg return expand_intrinsic_vastart (callexp); 895 1.1 mrg 896 1.1 mrg case INTRINSIC_ADDS: 897 1.1.1.3 mrg case INTRINSIC_ADDSL: 898 1.1.1.3 mrg case INTRINSIC_ADDU: 899 1.1.1.3 mrg case INTRINSIC_ADDUL: 900 1.1 mrg case INTRINSIC_SUBS: 901 1.1.1.3 mrg case INTRINSIC_SUBSL: 902 1.1.1.3 mrg case INTRINSIC_SUBU: 903 1.1.1.3 mrg case INTRINSIC_SUBUL: 904 1.1 mrg case INTRINSIC_MULS: 905 1.1.1.3 mrg case INTRINSIC_MULSL: 906 1.1.1.3 mrg case INTRINSIC_MULU: 907 1.1.1.3 mrg case INTRINSIC_MULUI: 908 1.1.1.3 mrg case INTRINSIC_MULUL: 909 1.1 mrg case INTRINSIC_NEGS: 910 1.1.1.3 mrg case INTRINSIC_NEGSL: 911 1.1 mrg return expand_intrinsic_checkedint (intrinsic, callexp); 912 1.1 mrg 913 1.1.1.3 mrg case INTRINSIC_VLOAD8: 914 1.1.1.3 mrg case INTRINSIC_VLOAD16: 915 1.1.1.3 mrg case INTRINSIC_VLOAD32: 916 1.1.1.3 mrg case INTRINSIC_VLOAD64: 917 1.1 mrg return expand_volatile_load (callexp); 918 1.1 mrg 919 1.1.1.3 mrg case INTRINSIC_VSTORE8: 920 1.1.1.3 mrg case INTRINSIC_VSTORE16: 921 1.1.1.3 mrg case INTRINSIC_VSTORE32: 922 1.1.1.3 mrg case INTRINSIC_VSTORE64: 923 1.1 mrg return expand_volatile_store (callexp); 924 1.1 mrg 925 1.1 mrg default: 926 1.1 mrg gcc_unreachable (); 927 1.1 mrg } 928 1.1 mrg } 929