intrinsics.cc revision 1.1 1 1.1 mrg /* intrinsics.cc -- D language compiler intrinsics.
2 1.1 mrg Copyright (C) 2006-2019 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 mrg #include "dmd/identifier.h"
24 1.1 mrg #include "dmd/mangle.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 mrg /* The DECL_FUNCTION_CODE of this decl. */
44 1.1 mrg intrinsic_code code;
45 1.1 mrg
46 1.1 mrg /* The name of the intrinsic. */
47 1.1 mrg const char *name;
48 1.1 mrg
49 1.1 mrg /* The module where the intrinsic is located. */
50 1.1 mrg const char *module;
51 1.1 mrg
52 1.1 mrg /* The mangled signature decoration of the intrinsic. */
53 1.1 mrg const char *deco;
54 1.1 mrg
55 1.1 mrg /* True if the intrinsic is only handled in CTFE. */
56 1.1 mrg bool ctfeonly;
57 1.1 mrg };
58 1.1 mrg
59 1.1 mrg static const intrinsic_decl intrinsic_decls[] =
60 1.1 mrg {
61 1.1 mrg #define DEF_D_INTRINSIC(CODE, ALIAS, NAME, MODULE, DECO, CTFE) \
62 1.1 mrg { INTRINSIC_ ## ALIAS, NAME, MODULE, DECO, CTFE },
63 1.1 mrg
64 1.1 mrg #include "intrinsics.def"
65 1.1 mrg
66 1.1 mrg #undef DEF_D_INTRINSIC
67 1.1 mrg };
68 1.1 mrg
69 1.1 mrg /* Checks if DECL is an intrinsic or run time library function that requires
70 1.1 mrg special processing. Sets DECL_INTRINSIC_CODE so it can be identified
71 1.1 mrg later in maybe_expand_intrinsic. */
72 1.1 mrg
73 1.1 mrg void
74 1.1 mrg maybe_set_intrinsic (FuncDeclaration *decl)
75 1.1 mrg {
76 1.1 mrg if (!decl->ident || decl->builtin != BUILTINunknown)
77 1.1 mrg return;
78 1.1 mrg
79 1.1 mrg /* The builtin flag is updated only if we can evaluate the intrinsic
80 1.1 mrg at compile-time. Such as the math or bitop intrinsics. */
81 1.1 mrg decl->builtin = BUILTINno;
82 1.1 mrg
83 1.1 mrg /* Check if it's a compiler intrinsic. We only require that any
84 1.1 mrg internally recognised intrinsics are declared in a module with
85 1.1 mrg an explicit module declaration. */
86 1.1 mrg Module *m = decl->getModule ();
87 1.1 mrg
88 1.1 mrg if (!m || !m->md)
89 1.1 mrg return;
90 1.1 mrg
91 1.1 mrg TemplateInstance *ti = decl->isInstantiated ();
92 1.1 mrg TemplateDeclaration *td = ti ? ti->tempdecl->isTemplateDeclaration () : NULL;
93 1.1 mrg
94 1.1 mrg const char *tname = decl->ident->toChars ();
95 1.1 mrg const char *tmodule = m->md->toChars ();
96 1.1 mrg const char *tdeco = (td == NULL) ? decl->type->deco : NULL;
97 1.1 mrg
98 1.1 mrg /* Look through all D intrinsics. */
99 1.1 mrg for (size_t i = 0; i < (int) INTRINSIC_LAST; i++)
100 1.1 mrg {
101 1.1 mrg if (!intrinsic_decls[i].name)
102 1.1 mrg continue;
103 1.1 mrg
104 1.1 mrg if (strcmp (intrinsic_decls[i].name, tname) != 0
105 1.1 mrg || strcmp (intrinsic_decls[i].module, tmodule) != 0)
106 1.1 mrg continue;
107 1.1 mrg
108 1.1 mrg /* Instantiated functions would have the wrong type deco, get it from the
109 1.1 mrg template member instead. */
110 1.1 mrg if (tdeco == NULL)
111 1.1 mrg {
112 1.1 mrg if (!td || !td->onemember)
113 1.1 mrg return;
114 1.1 mrg
115 1.1 mrg FuncDeclaration *fd = td->onemember->isFuncDeclaration ();
116 1.1 mrg if (fd == NULL)
117 1.1 mrg return;
118 1.1 mrg
119 1.1 mrg OutBuffer buf;
120 1.1 mrg mangleToBuffer (fd->type, &buf);
121 1.1 mrg tdeco = buf.extractString ();
122 1.1 mrg }
123 1.1 mrg
124 1.1 mrg /* Matching the type deco may be a bit too strict, as it means that all
125 1.1 mrg function attributes that end up in the signature must be kept aligned
126 1.1 mrg between the compiler and library declaration. */
127 1.1 mrg if (strcmp (intrinsic_decls[i].deco, tdeco) == 0)
128 1.1 mrg {
129 1.1 mrg intrinsic_code code = intrinsic_decls[i].code;
130 1.1 mrg
131 1.1 mrg if (decl->csym == NULL)
132 1.1 mrg get_symbol_decl (decl);
133 1.1 mrg
134 1.1 mrg /* If there is no function body, then the implementation is always
135 1.1 mrg provided by the compiler. */
136 1.1 mrg if (!decl->fbody)
137 1.1 mrg {
138 1.1 mrg DECL_BUILT_IN_CLASS (decl->csym) = BUILT_IN_FRONTEND;
139 1.1 mrg DECL_FUNCTION_CODE (decl->csym) = (built_in_function) code;
140 1.1 mrg }
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 mrg case INTRINSIC_SUBS:
151 1.1 mrg case INTRINSIC_MULS:
152 1.1 mrg case INTRINSIC_NEGS:
153 1.1 mrg case INTRINSIC_VLOAD:
154 1.1 mrg case INTRINSIC_VSTORE:
155 1.1 mrg break;
156 1.1 mrg
157 1.1 mrg case INTRINSIC_POW:
158 1.1 mrg {
159 1.1 mrg /* Check that this overload of pow() is has an equivalent
160 1.1 mrg built-in function. It could be `int pow(int, int)'. */
161 1.1 mrg tree rettype = TREE_TYPE (TREE_TYPE (decl->csym));
162 1.1 mrg if (mathfn_built_in (rettype, BUILT_IN_POW) != NULL_TREE)
163 1.1 mrg decl->builtin = BUILTINyes;
164 1.1 mrg break;
165 1.1 mrg }
166 1.1 mrg
167 1.1 mrg default:
168 1.1 mrg decl->builtin = BUILTINyes;
169 1.1 mrg break;
170 1.1 mrg }
171 1.1 mrg
172 1.1 mrg /* The intrinsic was marked as CTFE-only. */
173 1.1 mrg if (intrinsic_decls[i].ctfeonly)
174 1.1 mrg DECL_BUILT_IN_CTFE (decl->csym) = 1;
175 1.1 mrg
176 1.1 mrg DECL_INTRINSIC_CODE (decl->csym) = code;
177 1.1 mrg break;
178 1.1 mrg }
179 1.1 mrg }
180 1.1 mrg }
181 1.1 mrg
182 1.1 mrg /* Construct a function call to the built-in function CODE, N is the number of
183 1.1 mrg arguments, and the `...' parameters are the argument expressions.
184 1.1 mrg The original call expression is held in CALLEXP. */
185 1.1 mrg
186 1.1 mrg static tree
187 1.1 mrg call_builtin_fn (tree callexp, built_in_function code, int n, ...)
188 1.1 mrg {
189 1.1 mrg tree *argarray = XALLOCAVEC (tree, n);
190 1.1 mrg va_list ap;
191 1.1 mrg
192 1.1 mrg va_start (ap, n);
193 1.1 mrg for (int i = 0; i < n; i++)
194 1.1 mrg argarray[i] = va_arg (ap, tree);
195 1.1 mrg va_end (ap);
196 1.1 mrg
197 1.1 mrg tree exp = build_call_expr_loc_array (EXPR_LOCATION (callexp),
198 1.1 mrg builtin_decl_explicit (code),
199 1.1 mrg n, argarray);
200 1.1 mrg return convert (TREE_TYPE (callexp), fold (exp));
201 1.1 mrg }
202 1.1 mrg
203 1.1 mrg /* Expand a front-end instrinsic call to bsf(). This takes one argument,
204 1.1 mrg the signature to which can be either:
205 1.1 mrg
206 1.1 mrg int bsf (uint arg);
207 1.1 mrg int bsf (ulong arg);
208 1.1 mrg
209 1.1 mrg This scans all bits in the given argument starting with the first,
210 1.1 mrg returning the bit number of the first bit set. The original call
211 1.1 mrg expression is held in CALLEXP. */
212 1.1 mrg
213 1.1 mrg static tree
214 1.1 mrg expand_intrinsic_bsf (tree callexp)
215 1.1 mrg {
216 1.1 mrg /* The bsr() intrinsic gets turned into __builtin_ctz(arg).
217 1.1 mrg The return value is supposed to be undefined if arg is zero. */
218 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0);
219 1.1 mrg int argsize = TYPE_PRECISION (TREE_TYPE (arg));
220 1.1 mrg
221 1.1 mrg /* Which variant of __builtin_ctz* should we call? */
222 1.1 mrg built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_CTZ
223 1.1 mrg : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_CTZL
224 1.1 mrg : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_CTZLL
225 1.1 mrg : END_BUILTINS;
226 1.1 mrg
227 1.1 mrg gcc_assert (code != END_BUILTINS);
228 1.1 mrg
229 1.1 mrg return call_builtin_fn (callexp, code, 1, arg);
230 1.1 mrg }
231 1.1 mrg
232 1.1 mrg /* Expand a front-end instrinsic call to bsr(). This takes one argument,
233 1.1 mrg the signature to which can be either:
234 1.1 mrg
235 1.1 mrg int bsr (uint arg);
236 1.1 mrg int bsr (ulong arg);
237 1.1 mrg
238 1.1 mrg This scans all bits in the given argument from the most significant bit
239 1.1 mrg to the least significant, returning the bit number of the first bit set.
240 1.1 mrg The original call expression is held in CALLEXP. */
241 1.1 mrg
242 1.1 mrg static tree
243 1.1 mrg expand_intrinsic_bsr (tree callexp)
244 1.1 mrg {
245 1.1 mrg /* The bsr() intrinsic gets turned into (size - 1) - __builtin_clz(arg).
246 1.1 mrg The return value is supposed to be undefined if arg is zero. */
247 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0);
248 1.1 mrg tree type = TREE_TYPE (arg);
249 1.1 mrg int argsize = TYPE_PRECISION (type);
250 1.1 mrg
251 1.1 mrg /* Which variant of __builtin_clz* should we call? */
252 1.1 mrg built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_CLZ
253 1.1 mrg : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_CLZL
254 1.1 mrg : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_CLZLL
255 1.1 mrg : END_BUILTINS;
256 1.1 mrg
257 1.1 mrg gcc_assert (code != END_BUILTINS);
258 1.1 mrg
259 1.1 mrg tree result = call_builtin_fn (callexp, code, 1, arg);
260 1.1 mrg
261 1.1 mrg /* Handle int -> long conversions. */
262 1.1 mrg if (TREE_TYPE (result) != type)
263 1.1 mrg result = fold_convert (type, result);
264 1.1 mrg
265 1.1 mrg result = fold_build2 (MINUS_EXPR, type,
266 1.1 mrg build_integer_cst (argsize - 1, type), result);
267 1.1 mrg return fold_convert (TREE_TYPE (callexp), result);
268 1.1 mrg }
269 1.1 mrg
270 1.1 mrg /* Expand a front-end intrinsic call to INTRINSIC, which is either a call to
271 1.1 mrg bt(), btc(), btr(), or bts(). These intrinsics expect to take two arguments,
272 1.1 mrg the signature to which is:
273 1.1 mrg
274 1.1 mrg int bt (size_t* ptr, size_t bitnum);
275 1.1 mrg
276 1.1 mrg All intrinsics test if a bit is set and return the result of that condition.
277 1.1 mrg Variants of `bt' will then update that bit. `btc' compliments the bit, `bts'
278 1.1 mrg sets the bit, and `btr' resets the bit. The original call expression is
279 1.1 mrg held in CALLEXP. */
280 1.1 mrg
281 1.1 mrg static tree
282 1.1 mrg expand_intrinsic_bt (intrinsic_code intrinsic, tree callexp)
283 1.1 mrg {
284 1.1 mrg tree ptr = CALL_EXPR_ARG (callexp, 0);
285 1.1 mrg tree bitnum = CALL_EXPR_ARG (callexp, 1);
286 1.1 mrg tree type = TREE_TYPE (TREE_TYPE (ptr));
287 1.1 mrg
288 1.1 mrg /* size_t bitsize = sizeof(*ptr) * BITS_PER_UNIT; */
289 1.1 mrg tree bitsize = fold_convert (type, TYPE_SIZE (type));
290 1.1 mrg
291 1.1 mrg /* ptr[bitnum / bitsize] */
292 1.1 mrg ptr = build_array_index (ptr, fold_build2 (TRUNC_DIV_EXPR, type,
293 1.1 mrg bitnum, bitsize));
294 1.1 mrg ptr = indirect_ref (type, ptr);
295 1.1 mrg
296 1.1 mrg /* mask = 1 << (bitnum % bitsize); */
297 1.1 mrg bitnum = fold_build2 (TRUNC_MOD_EXPR, type, bitnum, bitsize);
298 1.1 mrg bitnum = fold_build2 (LSHIFT_EXPR, type, size_one_node, bitnum);
299 1.1 mrg
300 1.1 mrg /* cond = ptr[bitnum / size] & mask; */
301 1.1 mrg tree cond = fold_build2 (BIT_AND_EXPR, type, ptr, bitnum);
302 1.1 mrg
303 1.1 mrg /* cond ? -1 : 0; */
304 1.1 mrg cond = build_condition (TREE_TYPE (callexp), d_truthvalue_conversion (cond),
305 1.1 mrg integer_minus_one_node, integer_zero_node);
306 1.1 mrg
307 1.1 mrg /* Update the bit as needed, only testing the bit for bt(). */
308 1.1 mrg if (intrinsic == INTRINSIC_BT)
309 1.1 mrg return cond;
310 1.1 mrg
311 1.1 mrg tree_code code = (intrinsic == INTRINSIC_BTC) ? BIT_XOR_EXPR
312 1.1 mrg : (intrinsic == INTRINSIC_BTR) ? BIT_AND_EXPR
313 1.1 mrg : (intrinsic == INTRINSIC_BTS) ? BIT_IOR_EXPR
314 1.1 mrg : ERROR_MARK;
315 1.1 mrg gcc_assert (code != ERROR_MARK);
316 1.1 mrg
317 1.1 mrg /* ptr[bitnum / size] op= mask; */
318 1.1 mrg if (intrinsic == INTRINSIC_BTR)
319 1.1 mrg bitnum = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (bitnum), bitnum);
320 1.1 mrg
321 1.1 mrg ptr = modify_expr (ptr, fold_build2 (code, TREE_TYPE (ptr), ptr, bitnum));
322 1.1 mrg
323 1.1 mrg /* Store the condition result in a temporary, and return expressions in
324 1.1 mrg correct order of evaluation. */
325 1.1 mrg tree tmp = build_local_temp (TREE_TYPE (callexp));
326 1.1 mrg cond = modify_expr (tmp, cond);
327 1.1 mrg
328 1.1 mrg return compound_expr (cond, compound_expr (ptr, tmp));
329 1.1 mrg }
330 1.1 mrg
331 1.1 mrg /* Expand a front-end intrinsic call to bswap(). This takes one argument, the
332 1.1 mrg signature to which can be either:
333 1.1 mrg
334 1.1 mrg int bswap (uint arg);
335 1.1 mrg int bswap (ulong arg);
336 1.1 mrg
337 1.1 mrg This swaps all bytes in an N byte type end-to-end. The original call
338 1.1 mrg expression is held in CALLEXP. */
339 1.1 mrg
340 1.1 mrg static tree
341 1.1 mrg expand_intrinsic_bswap (tree callexp)
342 1.1 mrg {
343 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0);
344 1.1 mrg int argsize = TYPE_PRECISION (TREE_TYPE (arg));
345 1.1 mrg
346 1.1 mrg /* Which variant of __builtin_bswap* should we call? */
347 1.1 mrg built_in_function code = (argsize == 32) ? BUILT_IN_BSWAP32
348 1.1 mrg : (argsize == 64) ? BUILT_IN_BSWAP64
349 1.1 mrg : END_BUILTINS;
350 1.1 mrg
351 1.1 mrg gcc_assert (code != END_BUILTINS);
352 1.1 mrg
353 1.1 mrg return call_builtin_fn (callexp, code, 1, arg);
354 1.1 mrg }
355 1.1 mrg
356 1.1 mrg /* Expand a front-end intrinsic call to popcnt(). This takes one argument, the
357 1.1 mrg signature to which can be either:
358 1.1 mrg
359 1.1 mrg int popcnt (uint arg);
360 1.1 mrg int popcnt (ulong arg);
361 1.1 mrg
362 1.1 mrg Calculates the number of set bits in an integer. The original call
363 1.1 mrg expression is held in CALLEXP. */
364 1.1 mrg
365 1.1 mrg static tree
366 1.1 mrg expand_intrinsic_popcnt (tree callexp)
367 1.1 mrg {
368 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0);
369 1.1 mrg int argsize = TYPE_PRECISION (TREE_TYPE (arg));
370 1.1 mrg
371 1.1 mrg /* Which variant of __builtin_popcount* should we call? */
372 1.1 mrg built_in_function code = (argsize <= INT_TYPE_SIZE) ? BUILT_IN_POPCOUNT
373 1.1 mrg : (argsize <= LONG_TYPE_SIZE) ? BUILT_IN_POPCOUNTL
374 1.1 mrg : (argsize <= LONG_LONG_TYPE_SIZE) ? BUILT_IN_POPCOUNTLL
375 1.1 mrg : END_BUILTINS;
376 1.1 mrg
377 1.1 mrg gcc_assert (code != END_BUILTINS);
378 1.1 mrg
379 1.1 mrg return call_builtin_fn (callexp, code, 1, arg);
380 1.1 mrg }
381 1.1 mrg
382 1.1 mrg /* Expand a front-end intrinsic call to INTRINSIC, which is either a call to
383 1.1 mrg sqrt(), sqrtf(), sqrtl(). These intrinsics expect to take one argument,
384 1.1 mrg the signature to which can be either:
385 1.1 mrg
386 1.1 mrg float sqrt (float arg);
387 1.1 mrg double sqrt (double arg);
388 1.1 mrg real sqrt (real arg);
389 1.1 mrg
390 1.1 mrg This computes the square root of the given argument. The original call
391 1.1 mrg expression is held in CALLEXP. */
392 1.1 mrg
393 1.1 mrg static tree
394 1.1 mrg expand_intrinsic_sqrt (intrinsic_code intrinsic, tree callexp)
395 1.1 mrg {
396 1.1 mrg tree arg = CALL_EXPR_ARG (callexp, 0);
397 1.1 mrg
398 1.1 mrg /* Which variant of __builtin_sqrt* should we call? */
399 1.1 mrg built_in_function code = (intrinsic == INTRINSIC_SQRT) ? BUILT_IN_SQRT
400 1.1 mrg : (intrinsic == INTRINSIC_SQRTF) ? BUILT_IN_SQRTF
401 1.1 mrg : (intrinsic == INTRINSIC_SQRTL) ? BUILT_IN_SQRTL
402 1.1 mrg : END_BUILTINS;
403 1.1 mrg
404 1.1 mrg gcc_assert (code != END_BUILTINS);
405 1.1 mrg return call_builtin_fn (callexp, code, 1, arg);
406 1.1 mrg }
407 1.1 mrg
408 1.1 mrg /* Expand a front-end intrinsic call to copysign(). This takes two arguments,
409 1.1 mrg the signature to which can be either:
410 1.1 mrg
411 1.1 mrg float copysign (T to, float from);
412 1.1 mrg double copysign (T to, double from);
413 1.1 mrg real copysign (T to, real from);
414 1.1 mrg
415 1.1 mrg This computes a value composed of TO with the sign bit of FROM. The original
416 1.1 mrg call expression is held in CALLEXP. */
417 1.1 mrg
418 1.1 mrg static tree
419 1.1 mrg expand_intrinsic_copysign (tree callexp)
420 1.1 mrg {
421 1.1 mrg tree to = CALL_EXPR_ARG (callexp, 0);
422 1.1 mrg tree from = CALL_EXPR_ARG (callexp, 1);
423 1.1 mrg tree type = TREE_TYPE (to);
424 1.1 mrg
425 1.1 mrg /* Convert parameters to the same type. Prefer the first parameter unless it
426 1.1 mrg is an integral type. */
427 1.1 mrg if (INTEGRAL_TYPE_P (type))
428 1.1 mrg {
429 1.1 mrg to = fold_convert (TREE_TYPE (from), to);
430 1.1 mrg type = TREE_TYPE (to);
431 1.1 mrg }
432 1.1 mrg else
433 1.1 mrg from = fold_convert (type, from);
434 1.1 mrg
435 1.1 mrg /* Which variant of __builtin_copysign* should we call? */
436 1.1 mrg tree builtin = mathfn_built_in (type, BUILT_IN_COPYSIGN);
437 1.1 mrg gcc_assert (builtin != NULL_TREE);
438 1.1 mrg
439 1.1 mrg return call_builtin_fn (callexp, DECL_FUNCTION_CODE (builtin), 2,
440 1.1 mrg to, from);
441 1.1 mrg }
442 1.1 mrg
443 1.1 mrg /* Expand a front-end intrinsic call to pow(). This takes two arguments, the
444 1.1 mrg signature to which can be either:
445 1.1 mrg
446 1.1 mrg float pow (float base, T exponent);
447 1.1 mrg double pow (double base, T exponent);
448 1.1 mrg real pow (real base, T exponent);
449 1.1 mrg
450 1.1 mrg This computes the value of BASE raised to the power of EXPONENT.
451 1.1 mrg The original call expression is held in CALLEXP. */
452 1.1 mrg
453 1.1 mrg static tree
454 1.1 mrg expand_intrinsic_pow (tree callexp)
455 1.1 mrg {
456 1.1 mrg tree base = CALL_EXPR_ARG (callexp, 0);
457 1.1 mrg tree exponent = CALL_EXPR_ARG (callexp, 1);
458 1.1 mrg tree exptype = TREE_TYPE (exponent);
459 1.1 mrg
460 1.1 mrg /* Which variant of __builtin_pow* should we call? */
461 1.1 mrg built_in_function code = SCALAR_FLOAT_TYPE_P (exptype) ? BUILT_IN_POW
462 1.1 mrg : INTEGRAL_TYPE_P (exptype) ? BUILT_IN_POWI
463 1.1 mrg : END_BUILTINS;
464 1.1 mrg gcc_assert (code != END_BUILTINS);
465 1.1 mrg
466 1.1 mrg tree builtin = mathfn_built_in (TREE_TYPE (base), code);
467 1.1 mrg gcc_assert (builtin != NULL_TREE);
468 1.1 mrg
469 1.1 mrg return call_builtin_fn (callexp, DECL_FUNCTION_CODE (builtin), 2,
470 1.1 mrg base, exponent);
471 1.1 mrg }
472 1.1 mrg
473 1.1 mrg /* Expand a front-end intrinsic call to va_arg(). This takes either one or two
474 1.1 mrg arguments, the signature to which can be either:
475 1.1 mrg
476 1.1 mrg T va_arg(T) (ref va_list ap);
477 1.1 mrg void va_arg(T) (va_list ap, ref T parmn);
478 1.1 mrg
479 1.1 mrg This retrieves the next variadic parameter that is type T from the given
480 1.1 mrg va_list. If also given, store the value into parmn, otherwise return it.
481 1.1 mrg The original call expression is held in CALLEXP. */
482 1.1 mrg
483 1.1 mrg static tree
484 1.1 mrg expand_intrinsic_vaarg (tree callexp)
485 1.1 mrg {
486 1.1 mrg tree ap = CALL_EXPR_ARG (callexp, 0);
487 1.1 mrg tree parmn = NULL_TREE;
488 1.1 mrg tree type;
489 1.1 mrg
490 1.1 mrg STRIP_NOPS (ap);
491 1.1 mrg
492 1.1 mrg if (call_expr_nargs (callexp) == 1)
493 1.1 mrg type = TREE_TYPE (callexp);
494 1.1 mrg else
495 1.1 mrg {
496 1.1 mrg parmn = CALL_EXPR_ARG (callexp, 1);
497 1.1 mrg STRIP_NOPS (parmn);
498 1.1 mrg gcc_assert (TREE_CODE (parmn) == ADDR_EXPR);
499 1.1 mrg parmn = TREE_OPERAND (parmn, 0);
500 1.1 mrg type = TREE_TYPE (parmn);
501 1.1 mrg }
502 1.1 mrg
503 1.1 mrg /* (T) VA_ARG_EXP<ap>; */
504 1.1 mrg tree exp = build1 (VA_ARG_EXPR, type, ap);
505 1.1 mrg
506 1.1 mrg /* parmn = (T) VA_ARG_EXP<ap>; */
507 1.1 mrg if (parmn != NULL_TREE)
508 1.1 mrg exp = modify_expr (parmn, exp);
509 1.1 mrg
510 1.1 mrg return exp;
511 1.1 mrg }
512 1.1 mrg
513 1.1 mrg /* Expand a front-end intrinsic call to va_start(), which takes two arguments,
514 1.1 mrg the signature to which is:
515 1.1 mrg
516 1.1 mrg void va_start(T) (out va_list ap, ref T parmn);
517 1.1 mrg
518 1.1 mrg This initializes the va_list type, where parmn should be the last named
519 1.1 mrg parameter. The original call expression is held in CALLEXP. */
520 1.1 mrg
521 1.1 mrg static tree
522 1.1 mrg expand_intrinsic_vastart (tree callexp)
523 1.1 mrg {
524 1.1 mrg tree ap = CALL_EXPR_ARG (callexp, 0);
525 1.1 mrg tree parmn = CALL_EXPR_ARG (callexp, 1);
526 1.1 mrg
527 1.1 mrg STRIP_NOPS (ap);
528 1.1 mrg STRIP_NOPS (parmn);
529 1.1 mrg
530 1.1 mrg /* The va_list argument should already have its address taken. The second
531 1.1 mrg argument, however, is inout and that needs to be fixed to prevent a
532 1.1 mrg warning. Could be casting, so need to check type too? */
533 1.1 mrg gcc_assert (TREE_CODE (ap) == ADDR_EXPR && TREE_CODE (parmn) == ADDR_EXPR);
534 1.1 mrg
535 1.1 mrg /* Assuming nobody tries to change the return type. */
536 1.1 mrg parmn = TREE_OPERAND (parmn, 0);
537 1.1 mrg
538 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_VA_START, 2, ap, parmn);
539 1.1 mrg }
540 1.1 mrg
541 1.1 mrg /* Expand a front-end instrinsic call to INTRINSIC, which is either a call to
542 1.1 mrg adds(), addu(), subs(), subu(), negs(), muls(), or mulu(). These intrinsics
543 1.1 mrg expect to take two or three arguments, the signature to which can be either:
544 1.1 mrg
545 1.1 mrg int adds (int x, int y, ref bool overflow);
546 1.1 mrg long adds (long x, long y, ref bool overflow);
547 1.1 mrg int negs (int x, ref bool overflow);
548 1.1 mrg long negs (long x, ref bool overflow);
549 1.1 mrg
550 1.1 mrg This performs an operation on two signed or unsigned integers, checking for
551 1.1 mrg overflow. The overflow is sticky, meaning that a sequence of operations
552 1.1 mrg can be done and overflow need only be checked at the end. The original call
553 1.1 mrg expression is held in CALLEXP. */
554 1.1 mrg
555 1.1 mrg static tree
556 1.1 mrg expand_intrinsic_checkedint (intrinsic_code intrinsic, tree callexp)
557 1.1 mrg {
558 1.1 mrg tree type = TREE_TYPE (callexp);
559 1.1 mrg tree x;
560 1.1 mrg tree y;
561 1.1 mrg tree overflow;
562 1.1 mrg
563 1.1 mrg /* The negs() intrinsic gets turned into SUB_OVERFLOW (0, y). */
564 1.1 mrg if (intrinsic == INTRINSIC_NEGS)
565 1.1 mrg {
566 1.1 mrg x = fold_convert (type, integer_zero_node);
567 1.1 mrg y = CALL_EXPR_ARG (callexp, 0);
568 1.1 mrg overflow = CALL_EXPR_ARG (callexp, 1);
569 1.1 mrg }
570 1.1 mrg else
571 1.1 mrg {
572 1.1 mrg x = CALL_EXPR_ARG (callexp, 0);
573 1.1 mrg y = CALL_EXPR_ARG (callexp, 1);
574 1.1 mrg overflow = CALL_EXPR_ARG (callexp, 2);
575 1.1 mrg }
576 1.1 mrg
577 1.1 mrg /* Which variant of *_OVERFLOW should we generate? */
578 1.1 mrg internal_fn icode = (intrinsic == INTRINSIC_ADDS) ? IFN_ADD_OVERFLOW
579 1.1 mrg : (intrinsic == INTRINSIC_SUBS) ? IFN_SUB_OVERFLOW
580 1.1 mrg : (intrinsic == INTRINSIC_MULS) ? IFN_MUL_OVERFLOW
581 1.1 mrg : (intrinsic == INTRINSIC_NEGS) ? IFN_SUB_OVERFLOW
582 1.1 mrg : IFN_LAST;
583 1.1 mrg gcc_assert (icode != IFN_LAST);
584 1.1 mrg
585 1.1 mrg tree result
586 1.1 mrg = build_call_expr_internal_loc (EXPR_LOCATION (callexp), icode,
587 1.1 mrg build_complex_type (type), 2, x, y);
588 1.1 mrg
589 1.1 mrg STRIP_NOPS (overflow);
590 1.1 mrg overflow = build_deref (overflow);
591 1.1 mrg
592 1.1 mrg /* Assign returned result to overflow parameter, however if overflow is
593 1.1 mrg already true, maintain its value. */
594 1.1 mrg type = TREE_TYPE (overflow);
595 1.1 mrg result = save_expr (result);
596 1.1 mrg
597 1.1 mrg tree exp = fold_build2 (BIT_IOR_EXPR, type, overflow,
598 1.1 mrg fold_convert (type, imaginary_part (result)));
599 1.1 mrg exp = modify_expr (overflow, exp);
600 1.1 mrg
601 1.1 mrg /* Return the value of result. */
602 1.1 mrg return compound_expr (exp, real_part (result));
603 1.1 mrg }
604 1.1 mrg
605 1.1 mrg /* Expand a front-end instrinsic call to volatileLoad(). This takes one
606 1.1 mrg argument, the signature to which can be either:
607 1.1 mrg
608 1.1 mrg ubyte volatileLoad (ubyte* ptr);
609 1.1 mrg ushort volatileLoad (ushort* ptr);
610 1.1 mrg uint volatileLoad (uint* ptr);
611 1.1 mrg ulong volatileLoad (ulong* ptr);
612 1.1 mrg
613 1.1 mrg This reads a value from the memory location indicated by ptr. Calls to
614 1.1 mrg them are be guaranteed to not be removed (such as during DCE) or reordered
615 1.1 mrg in the same thread. The original call expression is held in CALLEXP. */
616 1.1 mrg
617 1.1 mrg static tree
618 1.1 mrg expand_volatile_load (tree callexp)
619 1.1 mrg {
620 1.1 mrg tree ptr = CALL_EXPR_ARG (callexp, 0);
621 1.1 mrg tree ptrtype = TREE_TYPE (ptr);
622 1.1 mrg gcc_assert (POINTER_TYPE_P (ptrtype));
623 1.1 mrg
624 1.1 mrg /* (T) *(volatile T *) ptr; */
625 1.1 mrg tree type = build_qualified_type (TREE_TYPE (ptrtype), TYPE_QUAL_VOLATILE);
626 1.1 mrg tree result = indirect_ref (type, ptr);
627 1.1 mrg TREE_THIS_VOLATILE (result) = 1;
628 1.1 mrg
629 1.1 mrg return result;
630 1.1 mrg }
631 1.1 mrg
632 1.1 mrg /* Expand a front-end instrinsic call to volatileStore(). This takes two
633 1.1 mrg arguments, the signature to which can be either:
634 1.1 mrg
635 1.1 mrg void volatileStore (ubyte* ptr, ubyte value);
636 1.1 mrg void volatileStore (ushort* ptr, ushort value);
637 1.1 mrg void volatileStore (uint* ptr, uint value);
638 1.1 mrg void volatileStore (ulong* ptr, ulong value);
639 1.1 mrg
640 1.1 mrg This writes a value to the memory location indicated by ptr. Calls to
641 1.1 mrg them are be guaranteed to not be removed (such as during DCE) or reordered
642 1.1 mrg in the same thread. The original call expression is held in CALLEXP. */
643 1.1 mrg
644 1.1 mrg static tree
645 1.1 mrg expand_volatile_store (tree callexp)
646 1.1 mrg {
647 1.1 mrg tree ptr = CALL_EXPR_ARG (callexp, 0);
648 1.1 mrg tree ptrtype = TREE_TYPE (ptr);
649 1.1 mrg gcc_assert (POINTER_TYPE_P (ptrtype));
650 1.1 mrg
651 1.1 mrg /* (T) *(volatile T *) ptr; */
652 1.1 mrg tree type = build_qualified_type (TREE_TYPE (ptrtype), TYPE_QUAL_VOLATILE);
653 1.1 mrg tree result = indirect_ref (type, ptr);
654 1.1 mrg TREE_THIS_VOLATILE (result) = 1;
655 1.1 mrg
656 1.1 mrg /* (*(volatile T *) ptr) = value; */
657 1.1 mrg tree value = CALL_EXPR_ARG (callexp, 1);
658 1.1 mrg return modify_expr (result, value);
659 1.1 mrg }
660 1.1 mrg
661 1.1 mrg /* If CALLEXP is for an intrinsic , expand and return inlined compiler
662 1.1 mrg generated instructions. Most map directly to GCC builtins, others
663 1.1 mrg require a little extra work around them. */
664 1.1 mrg
665 1.1 mrg tree
666 1.1 mrg maybe_expand_intrinsic (tree callexp)
667 1.1 mrg {
668 1.1 mrg tree callee = CALL_EXPR_FN (callexp);
669 1.1 mrg
670 1.1 mrg if (TREE_CODE (callee) == ADDR_EXPR)
671 1.1 mrg callee = TREE_OPERAND (callee, 0);
672 1.1 mrg
673 1.1 mrg if (TREE_CODE (callee) != FUNCTION_DECL)
674 1.1 mrg return callexp;
675 1.1 mrg
676 1.1 mrg /* Don't expand CTFE-only intrinsics outside of semantic processing. */
677 1.1 mrg if (DECL_BUILT_IN_CTFE (callee) && !doing_semantic_analysis_p)
678 1.1 mrg return callexp;
679 1.1 mrg
680 1.1 mrg intrinsic_code intrinsic = DECL_INTRINSIC_CODE (callee);
681 1.1 mrg built_in_function code;
682 1.1 mrg
683 1.1 mrg switch (intrinsic)
684 1.1 mrg {
685 1.1 mrg case INTRINSIC_NONE:
686 1.1 mrg return callexp;
687 1.1 mrg
688 1.1 mrg case INTRINSIC_BSF:
689 1.1 mrg return expand_intrinsic_bsf (callexp);
690 1.1 mrg
691 1.1 mrg case INTRINSIC_BSR:
692 1.1 mrg return expand_intrinsic_bsr (callexp);
693 1.1 mrg
694 1.1 mrg case INTRINSIC_BT:
695 1.1 mrg case INTRINSIC_BTC:
696 1.1 mrg case INTRINSIC_BTR:
697 1.1 mrg case INTRINSIC_BTS:
698 1.1 mrg return expand_intrinsic_bt (intrinsic, callexp);
699 1.1 mrg
700 1.1 mrg case INTRINSIC_BSWAP:
701 1.1 mrg return expand_intrinsic_bswap (callexp);
702 1.1 mrg
703 1.1 mrg case INTRINSIC_POPCNT:
704 1.1 mrg return expand_intrinsic_popcnt (callexp);
705 1.1 mrg
706 1.1 mrg case INTRINSIC_COS:
707 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_COSL, 1,
708 1.1 mrg CALL_EXPR_ARG (callexp, 0));
709 1.1 mrg
710 1.1 mrg case INTRINSIC_SIN:
711 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_SINL, 1,
712 1.1 mrg CALL_EXPR_ARG (callexp, 0));
713 1.1 mrg
714 1.1 mrg case INTRINSIC_RNDTOL:
715 1.1 mrg /* Not sure if llroundl stands as a good replacement for the
716 1.1 mrg expected behavior of rndtol. */
717 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_LLROUNDL, 1,
718 1.1 mrg CALL_EXPR_ARG (callexp, 0));
719 1.1 mrg
720 1.1 mrg case INTRINSIC_SQRT:
721 1.1 mrg case INTRINSIC_SQRTF:
722 1.1 mrg case INTRINSIC_SQRTL:
723 1.1 mrg return expand_intrinsic_sqrt (intrinsic, callexp);
724 1.1 mrg
725 1.1 mrg case INTRINSIC_LDEXP:
726 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_LDEXPL, 2,
727 1.1 mrg CALL_EXPR_ARG (callexp, 0),
728 1.1 mrg CALL_EXPR_ARG (callexp, 1));
729 1.1 mrg
730 1.1 mrg case INTRINSIC_FABS:
731 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_FABSL, 1,
732 1.1 mrg CALL_EXPR_ARG (callexp, 0));
733 1.1 mrg
734 1.1 mrg case INTRINSIC_RINT:
735 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_RINTL, 1,
736 1.1 mrg CALL_EXPR_ARG (callexp, 0));
737 1.1 mrg
738 1.1 mrg case INTRINSIC_TAN:
739 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_TANL, 1,
740 1.1 mrg CALL_EXPR_ARG (callexp, 0));
741 1.1 mrg
742 1.1 mrg case INTRINSIC_ISNAN:
743 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_ISNAN, 1,
744 1.1 mrg CALL_EXPR_ARG (callexp, 0));
745 1.1 mrg
746 1.1 mrg case INTRINSIC_ISINFINITY:
747 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_ISINF, 1,
748 1.1 mrg CALL_EXPR_ARG (callexp, 0));
749 1.1 mrg
750 1.1 mrg case INTRINSIC_ISFINITE:
751 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_ISFINITE, 1,
752 1.1 mrg CALL_EXPR_ARG (callexp, 0));
753 1.1 mrg
754 1.1 mrg case INTRINSIC_EXP:
755 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_EXPL, 1,
756 1.1 mrg CALL_EXPR_ARG (callexp, 0));
757 1.1 mrg
758 1.1 mrg case INTRINSIC_EXPM1:
759 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_EXPM1L, 1,
760 1.1 mrg CALL_EXPR_ARG (callexp, 0));
761 1.1 mrg
762 1.1 mrg case INTRINSIC_EXP2:
763 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_EXP2L, 1,
764 1.1 mrg CALL_EXPR_ARG (callexp, 0));
765 1.1 mrg
766 1.1 mrg case INTRINSIC_LOG:
767 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_LOGL, 1,
768 1.1 mrg CALL_EXPR_ARG (callexp, 0));
769 1.1 mrg
770 1.1 mrg case INTRINSIC_LOG2:
771 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_LOG2L, 1,
772 1.1 mrg CALL_EXPR_ARG (callexp, 0));
773 1.1 mrg
774 1.1 mrg case INTRINSIC_LOG10:
775 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_LOG10L, 1,
776 1.1 mrg CALL_EXPR_ARG (callexp, 0));
777 1.1 mrg
778 1.1 mrg case INTRINSIC_ROUND:
779 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_ROUNDL, 1,
780 1.1 mrg CALL_EXPR_ARG (callexp, 0));
781 1.1 mrg
782 1.1 mrg case INTRINSIC_FLOORF:
783 1.1 mrg case INTRINSIC_FLOOR:
784 1.1 mrg case INTRINSIC_FLOORL:
785 1.1 mrg code = (intrinsic == INTRINSIC_FLOOR) ? BUILT_IN_FLOOR
786 1.1 mrg : (intrinsic == INTRINSIC_FLOORF) ? BUILT_IN_FLOORF
787 1.1 mrg : BUILT_IN_FLOORL;
788 1.1 mrg return call_builtin_fn (callexp, code, 1, CALL_EXPR_ARG (callexp, 0));
789 1.1 mrg
790 1.1 mrg case INTRINSIC_CEILF:
791 1.1 mrg case INTRINSIC_CEIL:
792 1.1 mrg case INTRINSIC_CEILL:
793 1.1 mrg code = (intrinsic == INTRINSIC_CEIL) ? BUILT_IN_CEIL
794 1.1 mrg : (intrinsic == INTRINSIC_CEILF) ? BUILT_IN_CEILF
795 1.1 mrg : BUILT_IN_CEILL;
796 1.1 mrg return call_builtin_fn (callexp, code, 1, CALL_EXPR_ARG (callexp, 0));
797 1.1 mrg
798 1.1 mrg case INTRINSIC_TRUNC:
799 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_TRUNCL, 1,
800 1.1 mrg CALL_EXPR_ARG (callexp, 0));
801 1.1 mrg
802 1.1 mrg case INTRINSIC_FMIN:
803 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_FMINL, 2,
804 1.1 mrg CALL_EXPR_ARG (callexp, 0),
805 1.1 mrg CALL_EXPR_ARG (callexp, 1));
806 1.1 mrg
807 1.1 mrg case INTRINSIC_FMAX:
808 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_FMAXL, 2,
809 1.1 mrg CALL_EXPR_ARG (callexp, 0),
810 1.1 mrg CALL_EXPR_ARG (callexp, 1));
811 1.1 mrg
812 1.1 mrg case INTRINSIC_COPYSIGN:
813 1.1 mrg return expand_intrinsic_copysign (callexp);
814 1.1 mrg
815 1.1 mrg case INTRINSIC_POW:
816 1.1 mrg return expand_intrinsic_pow (callexp);
817 1.1 mrg
818 1.1 mrg case INTRINSIC_FMA:
819 1.1 mrg return call_builtin_fn (callexp, BUILT_IN_FMAL, 3,
820 1.1 mrg CALL_EXPR_ARG (callexp, 0),
821 1.1 mrg CALL_EXPR_ARG (callexp, 1),
822 1.1 mrg CALL_EXPR_ARG (callexp, 2));
823 1.1 mrg
824 1.1 mrg case INTRINSIC_VA_ARG:
825 1.1 mrg case INTRINSIC_C_VA_ARG:
826 1.1 mrg return expand_intrinsic_vaarg (callexp);
827 1.1 mrg
828 1.1 mrg case INTRINSIC_VASTART:
829 1.1 mrg return expand_intrinsic_vastart (callexp);
830 1.1 mrg
831 1.1 mrg case INTRINSIC_ADDS:
832 1.1 mrg case INTRINSIC_SUBS:
833 1.1 mrg case INTRINSIC_MULS:
834 1.1 mrg case INTRINSIC_NEGS:
835 1.1 mrg return expand_intrinsic_checkedint (intrinsic, callexp);
836 1.1 mrg
837 1.1 mrg case INTRINSIC_VLOAD:
838 1.1 mrg return expand_volatile_load (callexp);
839 1.1 mrg
840 1.1 mrg case INTRINSIC_VSTORE:
841 1.1 mrg return expand_volatile_store (callexp);
842 1.1 mrg
843 1.1 mrg default:
844 1.1 mrg gcc_unreachable ();
845 1.1 mrg }
846 1.1 mrg }
847