Home | History | Annotate | Line # | Download | only in d
      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