]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
In gcc/:
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
0b387d23 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
53800dbe 4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#include "config.h"
23#include "system.h"
24#include "machmode.h"
25#include "rtl.h"
26#include "tree.h"
27#include "obstack.h"
28#include "flags.h"
29#include "regs.h"
30#include "hard-reg-set.h"
31#include "except.h"
32#include "function.h"
33#include "insn-flags.h"
34#include "insn-codes.h"
35#include "insn-config.h"
36#include "expr.h"
37#include "recog.h"
38#include "output.h"
39#include "typeclass.h"
40#include "defaults.h"
41#include "toplev.h"
1dd6c958 42#include "tm_p.h"
53800dbe 43
44#define CALLED_AS_BUILT_IN(NODE) \
45 (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
46
53800dbe 47/* Register mappings for target machines without register windows. */
48#ifndef INCOMING_REGNO
49#define INCOMING_REGNO(OUT) (OUT)
50#endif
51#ifndef OUTGOING_REGNO
52#define OUTGOING_REGNO(IN) (IN)
53#endif
54
726e2588 55#ifndef PAD_VARARGS_DOWN
56#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
57#endif
58
ab7943b9 59/* Define the names of the builtin function types and codes. */
8934cb0c 60const char *const built_in_class_names[4]
ab7943b9 61 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
62
4e9d90c7 63#define DEF_BUILTIN(x) STRINGIFY(x),
8934cb0c 64const char *const built_in_names[(int) END_BUILTINS] =
4e9d90c7 65{
66#include "builtins.def"
67};
68#undef DEF_BUILTIN
ab7943b9 69
df94cd3b 70/* Setup an array of _DECL trees, make sure each element is
71 initialized to NULL_TREE. */
72#define DEF_BUILTIN(x) NULL_TREE,
73tree built_in_decls[(int) END_BUILTINS] =
74{
75#include "builtins.def"
76};
77#undef DEF_BUILTIN
78
6bcfea9e 79tree (*lang_type_promotes_to) PARAMS ((tree));
e94026da 80
6bcfea9e 81static int get_pointer_alignment PARAMS ((tree, unsigned));
82static tree c_strlen PARAMS ((tree));
83static rtx get_memory_rtx PARAMS ((tree));
84static int apply_args_size PARAMS ((void));
85static int apply_result_size PARAMS ((void));
d8c9779c 86#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
6bcfea9e 87static rtx result_vector PARAMS ((int, rtx));
d8c9779c 88#endif
6bcfea9e 89static rtx expand_builtin_apply_args PARAMS ((void));
90static rtx expand_builtin_apply_args_1 PARAMS ((void));
91static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx));
92static void expand_builtin_return PARAMS ((rtx));
93static rtx expand_builtin_classify_type PARAMS ((tree));
94static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
95static rtx expand_builtin_constant_p PARAMS ((tree));
96static rtx expand_builtin_args_info PARAMS ((tree));
97static rtx expand_builtin_next_arg PARAMS ((tree));
98static rtx expand_builtin_va_start PARAMS ((int, tree));
99static rtx expand_builtin_va_end PARAMS ((tree));
100static rtx expand_builtin_va_copy PARAMS ((tree));
95d038e4 101#ifdef HAVE_cmpstrsi
6bcfea9e 102static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx));
103static rtx expand_builtin_strcmp PARAMS ((tree, rtx));
95d038e4 104#endif
6bcfea9e 105static rtx expand_builtin_memcpy PARAMS ((tree));
106static rtx expand_builtin_strcpy PARAMS ((tree));
107static rtx expand_builtin_memset PARAMS ((tree));
ffc83088 108static rtx expand_builtin_bzero PARAMS ((tree));
ab7943b9 109static rtx expand_builtin_strlen PARAMS ((tree, rtx,
110 enum machine_mode));
17f5ea87 111static rtx expand_builtin_strstr PARAMS ((tree, rtx,
112 enum machine_mode));
6bcfea9e 113static rtx expand_builtin_alloca PARAMS ((tree, rtx));
114static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx));
115static rtx expand_builtin_frame_address PARAMS ((tree));
df94cd3b 116static rtx expand_builtin_fputs PARAMS ((tree, int));
6bcfea9e 117static tree stabilize_va_list PARAMS ((tree, int));
89cfe6e5 118static rtx expand_builtin_expect PARAMS ((tree, rtx));
650e4c94 119static tree fold_builtin_constant_p PARAMS ((tree));
53800dbe 120
121/* Return the alignment in bits of EXP, a pointer valued expression.
122 But don't return more than MAX_ALIGN no matter what.
123 The alignment returned is, by default, the alignment of the thing that
124 EXP points to (if it is not a POINTER_TYPE, 0 is returned).
125
126 Otherwise, look at the expression to see if we can do better, i.e., if the
127 expression is actually pointing at an object whose alignment is tighter. */
128
129static int
130get_pointer_alignment (exp, max_align)
131 tree exp;
132 unsigned max_align;
133{
134 unsigned align, inner;
135
136 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
137 return 0;
138
139 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
140 align = MIN (align, max_align);
141
142 while (1)
143 {
144 switch (TREE_CODE (exp))
145 {
146 case NOP_EXPR:
147 case CONVERT_EXPR:
148 case NON_LVALUE_EXPR:
149 exp = TREE_OPERAND (exp, 0);
150 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
151 return align;
325d1c45 152
53800dbe 153 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
154 align = MIN (inner, max_align);
155 break;
156
157 case PLUS_EXPR:
158 /* If sum of pointer + int, restrict our maximum alignment to that
159 imposed by the integer. If not, we can't do any better than
160 ALIGN. */
325d1c45 161 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 162 return align;
163
325d1c45 164 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1) * BITS_PER_UNIT)
53800dbe 165 & (max_align - 1))
166 != 0)
167 max_align >>= 1;
168
169 exp = TREE_OPERAND (exp, 0);
170 break;
171
172 case ADDR_EXPR:
173 /* See what we are pointing at and look at its alignment. */
174 exp = TREE_OPERAND (exp, 0);
175 if (TREE_CODE (exp) == FUNCTION_DECL)
176 align = FUNCTION_BOUNDARY;
9308e976 177 else if (DECL_P (exp))
53800dbe 178 align = DECL_ALIGN (exp);
179#ifdef CONSTANT_ALIGNMENT
180 else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
181 align = CONSTANT_ALIGNMENT (exp, align);
182#endif
183 return MIN (align, max_align);
184
185 default:
186 return align;
187 }
188 }
189}
190
191/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
192 way, because it could contain a zero byte in the middle.
193 TREE_STRING_LENGTH is the size of the character array, not the string.
194
902de8ed 195 The value returned is of type `ssizetype'.
196
53800dbe 197 Unfortunately, string_constant can't access the values of const char
198 arrays with initializers, so neither can we do so here. */
199
200static tree
201c_strlen (src)
202 tree src;
203{
204 tree offset_node;
205 int offset, max;
206 char *ptr;
207
208 src = string_constant (src, &offset_node);
209 if (src == 0)
210 return 0;
902de8ed 211
53800dbe 212 max = TREE_STRING_LENGTH (src);
213 ptr = TREE_STRING_POINTER (src);
902de8ed 214
53800dbe 215 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
216 {
217 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
218 compute the offset to the following null if we don't know where to
219 start searching for it. */
220 int i;
902de8ed 221
53800dbe 222 for (i = 0; i < max; i++)
223 if (ptr[i] == 0)
224 return 0;
902de8ed 225
53800dbe 226 /* We don't know the starting offset, but we do know that the string
227 has no internal zero bytes. We can assume that the offset falls
228 within the bounds of the string; otherwise, the programmer deserves
229 what he gets. Subtract the offset from the length of the string,
902de8ed 230 and return that. This would perhaps not be valid if we were dealing
231 with named arrays in addition to literal string constants. */
232
233 return size_diffop (size_int (max), offset_node);
53800dbe 234 }
235
236 /* We have a known offset into the string. Start searching there for
237 a null character. */
238 if (offset_node == 0)
239 offset = 0;
240 else
241 {
242 /* Did we get a long long offset? If so, punt. */
243 if (TREE_INT_CST_HIGH (offset_node) != 0)
244 return 0;
245 offset = TREE_INT_CST_LOW (offset_node);
246 }
902de8ed 247
53800dbe 248 /* If the offset is known to be out of bounds, warn, and call strlen at
249 runtime. */
250 if (offset < 0 || offset > max)
251 {
252 warning ("offset outside bounds of constant string");
253 return 0;
254 }
902de8ed 255
53800dbe 256 /* Use strlen to search for the first zero byte. Since any strings
257 constructed with build_string will have nulls appended, we win even
258 if we get handed something like (char[4])"abcd".
259
260 Since OFFSET is our starting index into the string, no further
261 calculation is needed. */
902de8ed 262 return ssize_int (strlen (ptr + offset));
53800dbe 263}
264
265/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
266 times to get the address of either a higher stack frame, or a return
267 address located within it (depending on FNDECL_CODE). */
902de8ed 268
53800dbe 269rtx
270expand_builtin_return_addr (fndecl_code, count, tem)
271 enum built_in_function fndecl_code;
272 int count;
273 rtx tem;
274{
275 int i;
276
277 /* Some machines need special handling before we can access
278 arbitrary frames. For example, on the sparc, we must first flush
279 all register windows to the stack. */
280#ifdef SETUP_FRAME_ADDRESSES
281 if (count > 0)
282 SETUP_FRAME_ADDRESSES ();
283#endif
284
285 /* On the sparc, the return address is not in the frame, it is in a
286 register. There is no way to access it off of the current frame
287 pointer, but it can be accessed off the previous frame pointer by
288 reading the value from the register window save area. */
289#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
290 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
291 count--;
292#endif
293
294 /* Scan back COUNT frames to the specified frame. */
295 for (i = 0; i < count; i++)
296 {
297 /* Assume the dynamic chain pointer is in the word that the
298 frame address points to, unless otherwise specified. */
299#ifdef DYNAMIC_CHAIN_ADDRESS
300 tem = DYNAMIC_CHAIN_ADDRESS (tem);
301#endif
302 tem = memory_address (Pmode, tem);
303 tem = copy_to_reg (gen_rtx_MEM (Pmode, tem));
f7c44134 304 MEM_ALIAS_SET (tem) = get_frame_alias_set ();
53800dbe 305 }
306
307 /* For __builtin_frame_address, return what we've got. */
308 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
309 return tem;
310
311 /* For __builtin_return_address, Get the return address from that
312 frame. */
313#ifdef RETURN_ADDR_RTX
314 tem = RETURN_ADDR_RTX (count, tem);
315#else
316 tem = memory_address (Pmode,
317 plus_constant (tem, GET_MODE_SIZE (Pmode)));
318 tem = gen_rtx_MEM (Pmode, tem);
f7c44134 319 MEM_ALIAS_SET (tem) = get_frame_alias_set ();
53800dbe 320#endif
321 return tem;
322}
323
f7c44134 324/* Alias set used for setjmp buffer. */
325static HOST_WIDE_INT setjmp_alias_set = -1;
326
53800dbe 327/* __builtin_setjmp is passed a pointer to an array of five words (not
328 all will be used on all machines). It operates similarly to the C
329 library function of the same name, but is more efficient. Much of
330 the code below (and for longjmp) is copied from the handling of
331 non-local gotos.
332
333 NOTE: This is intended for use by GNAT and the exception handling
334 scheme in the compiler and will only work in the method used by
335 them. */
336
337rtx
338expand_builtin_setjmp (buf_addr, target, first_label, next_label)
339 rtx buf_addr;
340 rtx target;
341 rtx first_label, next_label;
342{
343 rtx lab1 = gen_label_rtx ();
344 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
345 enum machine_mode value_mode;
346 rtx stack_save;
f7c44134 347 rtx mem;
53800dbe 348
349 value_mode = TYPE_MODE (integer_type_node);
350
f7c44134 351 if (setjmp_alias_set == -1)
352 setjmp_alias_set = new_alias_set ();
353
53800dbe 354#ifdef POINTERS_EXTEND_UNSIGNED
355 buf_addr = convert_memory_address (Pmode, buf_addr);
356#endif
357
37ae8504 358 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 359
360 if (target == 0 || GET_CODE (target) != REG
361 || REGNO (target) < FIRST_PSEUDO_REGISTER)
362 target = gen_reg_rtx (value_mode);
363
364 emit_queue ();
365
366 /* We store the frame pointer and the address of lab1 in the buffer
367 and use the rest of it for the stack save area, which is
368 machine-dependent. */
369
370#ifndef BUILTIN_SETJMP_FRAME_VALUE
371#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
372#endif
373
f7c44134 374 mem = gen_rtx_MEM (Pmode, buf_addr);
375 MEM_ALIAS_SET (mem) = setjmp_alias_set;
376 emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
377
378 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
379 MEM_ALIAS_SET (mem) = setjmp_alias_set;
380
381 emit_move_insn (validize_mem (mem),
53800dbe 382 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1)));
383
384 stack_save = gen_rtx_MEM (sa_mode,
385 plus_constant (buf_addr,
386 2 * GET_MODE_SIZE (Pmode)));
f7c44134 387 MEM_ALIAS_SET (stack_save) = setjmp_alias_set;
53800dbe 388 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
389
390 /* If there is further processing to do, do it. */
391#ifdef HAVE_builtin_setjmp_setup
392 if (HAVE_builtin_setjmp_setup)
393 emit_insn (gen_builtin_setjmp_setup (buf_addr));
394#endif
395
396 /* Set TARGET to zero and branch to the first-time-through label. */
397 emit_move_insn (target, const0_rtx);
398 emit_jump_insn (gen_jump (first_label));
399 emit_barrier ();
400 emit_label (lab1);
401
402 /* Tell flow about the strange goings on. Putting `lab1' on
403 `nonlocal_goto_handler_labels' to indicates that function
404 calls may traverse the arc back to this label. */
405
406 current_function_has_nonlocal_label = 1;
791dcc3a 407 nonlocal_goto_handler_labels
408 = gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
53800dbe 409
410 /* Clobber the FP when we get here, so we have to make sure it's
411 marked as used by this function. */
412 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
413
414 /* Mark the static chain as clobbered here so life information
415 doesn't get messed up for it. */
416 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
417
418 /* Now put in the code to restore the frame pointer, and argument
419 pointer, if needed. The code below is from expand_end_bindings
420 in stmt.c; see detailed documentation there. */
421#ifdef HAVE_nonlocal_goto
422 if (! HAVE_nonlocal_goto)
423#endif
424 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
425
426#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
427 if (fixed_regs[ARG_POINTER_REGNUM])
428 {
429#ifdef ELIMINABLE_REGS
430 size_t i;
431 static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
432
3098b2d3 433 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 434 if (elim_regs[i].from == ARG_POINTER_REGNUM
435 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
436 break;
437
3098b2d3 438 if (i == ARRAY_SIZE (elim_regs))
53800dbe 439#endif
440 {
441 /* Now restore our arg pointer from the address at which it
442 was saved in our stack frame.
443 If there hasn't be space allocated for it yet, make
444 some now. */
445 if (arg_pointer_save_area == 0)
446 arg_pointer_save_area
447 = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
448 emit_move_insn (virtual_incoming_args_rtx,
449 copy_to_reg (arg_pointer_save_area));
450 }
451 }
452#endif
453
454#ifdef HAVE_builtin_setjmp_receiver
455 if (HAVE_builtin_setjmp_receiver)
456 emit_insn (gen_builtin_setjmp_receiver (lab1));
457 else
458#endif
459#ifdef HAVE_nonlocal_goto_receiver
460 if (HAVE_nonlocal_goto_receiver)
461 emit_insn (gen_nonlocal_goto_receiver ());
462 else
463#endif
464 {
465 ; /* Nothing */
466 }
467
468 /* Set TARGET, and branch to the next-time-through label. */
469 emit_move_insn (target, const1_rtx);
470 emit_jump_insn (gen_jump (next_label));
471 emit_barrier ();
472
473 return target;
474}
475
476/* __builtin_longjmp is passed a pointer to an array of five words (not
477 all will be used on all machines). It operates similarly to the C
478 library function of the same name, but is more efficient. Much of
479 the code below is copied from the handling of non-local gotos.
480
481 NOTE: This is intended for use by GNAT and the exception handling
482 scheme in the compiler and will only work in the method used by
483 them. */
484
485void
486expand_builtin_longjmp (buf_addr, value)
487 rtx buf_addr, value;
488{
489 rtx fp, lab, stack;
490 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
491
f7c44134 492 if (setjmp_alias_set == -1)
493 setjmp_alias_set = new_alias_set ();
494
53800dbe 495#ifdef POINTERS_EXTEND_UNSIGNED
496 buf_addr = convert_memory_address (Pmode, buf_addr);
497#endif
498 buf_addr = force_reg (Pmode, buf_addr);
499
500 /* We used to store value in static_chain_rtx, but that fails if pointers
501 are smaller than integers. We instead require that the user must pass
502 a second argument of 1, because that is what builtin_setjmp will
503 return. This also makes EH slightly more efficient, since we are no
504 longer copying around a value that we don't care about. */
505 if (value != const1_rtx)
506 abort ();
507
508#ifdef HAVE_builtin_longjmp
509 if (HAVE_builtin_longjmp)
510 emit_insn (gen_builtin_longjmp (buf_addr));
511 else
512#endif
513 {
514 fp = gen_rtx_MEM (Pmode, buf_addr);
515 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
516 GET_MODE_SIZE (Pmode)));
517
518 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
519 2 * GET_MODE_SIZE (Pmode)));
f7c44134 520 MEM_ALIAS_SET (fp) = MEM_ALIAS_SET (lab) = MEM_ALIAS_SET (stack)
521 = setjmp_alias_set;
53800dbe 522
523 /* Pick up FP, label, and SP from the block and jump. This code is
524 from expand_goto in stmt.c; see there for detailed comments. */
525#if HAVE_nonlocal_goto
526 if (HAVE_nonlocal_goto)
527 /* We have to pass a value to the nonlocal_goto pattern that will
528 get copied into the static_chain pointer, but it does not matter
529 what that value is, because builtin_setjmp does not use it. */
530 emit_insn (gen_nonlocal_goto (value, fp, stack, lab));
531 else
532#endif
533 {
534 lab = copy_to_reg (lab);
535
536 emit_move_insn (hard_frame_pointer_rtx, fp);
537 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
538
539 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
540 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
541 emit_indirect_jump (lab);
542 }
543 }
544}
545
f7c44134 546/* Get a MEM rtx for expression EXP which is the address of an operand
547 to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
548
53800dbe 549static rtx
550get_memory_rtx (exp)
551 tree exp;
552{
f7c44134 553 rtx mem = gen_rtx_MEM (BLKmode,
554 memory_address (BLKmode,
555 expand_expr (exp, NULL_RTX,
556 ptr_mode, EXPAND_SUM)));
557
558 /* Get an expression we can use to find the attributes to assign to MEM.
559 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
560 we can. First remove any nops. */
561 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
562 || TREE_CODE (exp) == NON_LVALUE_EXPR)
563 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
564 exp = TREE_OPERAND (exp, 0);
565
566 if (TREE_CODE (exp) == ADDR_EXPR)
567 exp = TREE_OPERAND (exp, 0);
568 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
569 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
570 else
571 return mem;
53800dbe 572
f7c44134 573 set_mem_attributes (mem, exp, 0);
f488fae1 574
575 /* memcpy, memset and other builtin stringops can alias with anything. */
576 MEM_ALIAS_SET (mem) = 0;
53800dbe 577 return mem;
578}
579\f
580/* Built-in functions to perform an untyped call and return. */
581
582/* For each register that may be used for calling a function, this
583 gives a mode used to copy the register's value. VOIDmode indicates
584 the register is not used for calling a function. If the machine
585 has register windows, this gives only the outbound registers.
586 INCOMING_REGNO gives the corresponding inbound register. */
587static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
588
589/* For each register that may be used for returning values, this gives
590 a mode used to copy the register's value. VOIDmode indicates the
591 register is not used for returning values. If the machine has
592 register windows, this gives only the outbound registers.
593 INCOMING_REGNO gives the corresponding inbound register. */
594static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
595
596/* For each register that may be used for calling a function, this
597 gives the offset of that register into the block returned by
598 __builtin_apply_args. 0 indicates that the register is not
599 used for calling a function. */
600static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
601
602/* Return the offset of register REGNO into the block returned by
603 __builtin_apply_args. This is not declared static, since it is
604 needed in objc-act.c. */
605
606int
607apply_args_register_offset (regno)
608 int regno;
609{
610 apply_args_size ();
611
612 /* Arguments are always put in outgoing registers (in the argument
613 block) if such make sense. */
614#ifdef OUTGOING_REGNO
615 regno = OUTGOING_REGNO(regno);
616#endif
617 return apply_args_reg_offset[regno];
618}
619
620/* Return the size required for the block returned by __builtin_apply_args,
621 and initialize apply_args_mode. */
622
623static int
624apply_args_size ()
625{
626 static int size = -1;
627 int align, regno;
628 enum machine_mode mode;
629
630 /* The values computed by this function never change. */
631 if (size < 0)
632 {
633 /* The first value is the incoming arg-pointer. */
634 size = GET_MODE_SIZE (Pmode);
635
636 /* The second value is the structure value address unless this is
637 passed as an "invisible" first argument. */
638 if (struct_value_rtx)
639 size += GET_MODE_SIZE (Pmode);
640
641 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
642 if (FUNCTION_ARG_REGNO_P (regno))
643 {
644 /* Search for the proper mode for copying this register's
645 value. I'm not sure this is right, but it works so far. */
646 enum machine_mode best_mode = VOIDmode;
647
648 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
649 mode != VOIDmode;
650 mode = GET_MODE_WIDER_MODE (mode))
651 if (HARD_REGNO_MODE_OK (regno, mode)
652 && HARD_REGNO_NREGS (regno, mode) == 1)
653 best_mode = mode;
654
655 if (best_mode == VOIDmode)
656 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
657 mode != VOIDmode;
658 mode = GET_MODE_WIDER_MODE (mode))
659 if (HARD_REGNO_MODE_OK (regno, mode)
660 && (mov_optab->handlers[(int) mode].insn_code
661 != CODE_FOR_nothing))
662 best_mode = mode;
663
664 mode = best_mode;
665 if (mode == VOIDmode)
666 abort ();
667
668 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
669 if (size % align != 0)
670 size = CEIL (size, align) * align;
671 apply_args_reg_offset[regno] = size;
672 size += GET_MODE_SIZE (mode);
673 apply_args_mode[regno] = mode;
674 }
675 else
676 {
677 apply_args_mode[regno] = VOIDmode;
678 apply_args_reg_offset[regno] = 0;
679 }
680 }
681 return size;
682}
683
684/* Return the size required for the block returned by __builtin_apply,
685 and initialize apply_result_mode. */
686
687static int
688apply_result_size ()
689{
690 static int size = -1;
691 int align, regno;
692 enum machine_mode mode;
693
694 /* The values computed by this function never change. */
695 if (size < 0)
696 {
697 size = 0;
698
699 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
700 if (FUNCTION_VALUE_REGNO_P (regno))
701 {
702 /* Search for the proper mode for copying this register's
703 value. I'm not sure this is right, but it works so far. */
704 enum machine_mode best_mode = VOIDmode;
705
706 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
707 mode != TImode;
708 mode = GET_MODE_WIDER_MODE (mode))
709 if (HARD_REGNO_MODE_OK (regno, mode))
710 best_mode = mode;
711
712 if (best_mode == VOIDmode)
713 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
714 mode != VOIDmode;
715 mode = GET_MODE_WIDER_MODE (mode))
716 if (HARD_REGNO_MODE_OK (regno, mode)
717 && (mov_optab->handlers[(int) mode].insn_code
718 != CODE_FOR_nothing))
719 best_mode = mode;
720
721 mode = best_mode;
722 if (mode == VOIDmode)
723 abort ();
724
725 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
726 if (size % align != 0)
727 size = CEIL (size, align) * align;
728 size += GET_MODE_SIZE (mode);
729 apply_result_mode[regno] = mode;
730 }
731 else
732 apply_result_mode[regno] = VOIDmode;
733
734 /* Allow targets that use untyped_call and untyped_return to override
735 the size so that machine-specific information can be stored here. */
736#ifdef APPLY_RESULT_SIZE
737 size = APPLY_RESULT_SIZE;
738#endif
739 }
740 return size;
741}
742
743#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
744/* Create a vector describing the result block RESULT. If SAVEP is true,
745 the result block is used to save the values; otherwise it is used to
746 restore the values. */
747
748static rtx
749result_vector (savep, result)
750 int savep;
751 rtx result;
752{
753 int regno, size, align, nelts;
754 enum machine_mode mode;
755 rtx reg, mem;
756 rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
757
758 size = nelts = 0;
759 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
760 if ((mode = apply_result_mode[regno]) != VOIDmode)
761 {
762 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
763 if (size % align != 0)
764 size = CEIL (size, align) * align;
765 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
766 mem = change_address (result, mode,
767 plus_constant (XEXP (result, 0), size));
768 savevec[nelts++] = (savep
769 ? gen_rtx_SET (VOIDmode, mem, reg)
770 : gen_rtx_SET (VOIDmode, reg, mem));
771 size += GET_MODE_SIZE (mode);
772 }
773 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
774}
775#endif /* HAVE_untyped_call or HAVE_untyped_return */
776
777/* Save the state required to perform an untyped call with the same
778 arguments as were passed to the current function. */
779
780static rtx
781expand_builtin_apply_args_1 ()
782{
783 rtx registers;
784 int size, align, regno;
785 enum machine_mode mode;
786
787 /* Create a block where the arg-pointer, structure value address,
788 and argument registers can be saved. */
789 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
790
791 /* Walk past the arg-pointer and structure value address. */
792 size = GET_MODE_SIZE (Pmode);
793 if (struct_value_rtx)
794 size += GET_MODE_SIZE (Pmode);
795
796 /* Save each register used in calling a function to the block. */
797 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
798 if ((mode = apply_args_mode[regno]) != VOIDmode)
799 {
800 rtx tem;
801
802 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
803 if (size % align != 0)
804 size = CEIL (size, align) * align;
805
806 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
807
53800dbe 808 emit_move_insn (change_address (registers, mode,
809 plus_constant (XEXP (registers, 0),
810 size)),
811 tem);
812 size += GET_MODE_SIZE (mode);
813 }
814
815 /* Save the arg pointer to the block. */
816 emit_move_insn (change_address (registers, Pmode, XEXP (registers, 0)),
817 copy_to_reg (virtual_incoming_args_rtx));
818 size = GET_MODE_SIZE (Pmode);
819
820 /* Save the structure value address unless this is passed as an
821 "invisible" first argument. */
822 if (struct_value_incoming_rtx)
823 {
824 emit_move_insn (change_address (registers, Pmode,
825 plus_constant (XEXP (registers, 0),
826 size)),
827 copy_to_reg (struct_value_incoming_rtx));
828 size += GET_MODE_SIZE (Pmode);
829 }
830
831 /* Return the address of the block. */
832 return copy_addr_to_reg (XEXP (registers, 0));
833}
834
835/* __builtin_apply_args returns block of memory allocated on
836 the stack into which is stored the arg pointer, structure
837 value address, static chain, and all the registers that might
838 possibly be used in performing a function call. The code is
839 moved to the start of the function so the incoming values are
840 saved. */
841static rtx
842expand_builtin_apply_args ()
843{
844 /* Don't do __builtin_apply_args more than once in a function.
845 Save the result of the first call and reuse it. */
846 if (apply_args_value != 0)
847 return apply_args_value;
848 {
849 /* When this function is called, it means that registers must be
850 saved on entry to this function. So we migrate the
851 call to the first insn of this function. */
852 rtx temp;
853 rtx seq;
854
855 start_sequence ();
856 temp = expand_builtin_apply_args_1 ();
857 seq = get_insns ();
858 end_sequence ();
859
860 apply_args_value = temp;
861
862 /* Put the sequence after the NOTE that starts the function.
863 If this is inside a SEQUENCE, make the outer-level insn
864 chain current, so the code is placed at the start of the
865 function. */
866 push_topmost_sequence ();
867 emit_insns_before (seq, NEXT_INSN (get_insns ()));
868 pop_topmost_sequence ();
869 return temp;
870 }
871}
872
873/* Perform an untyped call and save the state required to perform an
874 untyped return of whatever value was returned by the given function. */
875
876static rtx
877expand_builtin_apply (function, arguments, argsize)
878 rtx function, arguments, argsize;
879{
880 int size, align, regno;
881 enum machine_mode mode;
882 rtx incoming_args, result, reg, dest, call_insn;
883 rtx old_stack_level = 0;
884 rtx call_fusage = 0;
885
886 /* Create a block where the return registers can be saved. */
887 result = assign_stack_local (BLKmode, apply_result_size (), -1);
888
53800dbe 889 /* Fetch the arg pointer from the ARGUMENTS block. */
890 incoming_args = gen_reg_rtx (Pmode);
891 emit_move_insn (incoming_args,
892 gen_rtx_MEM (Pmode, arguments));
893#ifndef STACK_GROWS_DOWNWARD
894 incoming_args = expand_binop (Pmode, sub_optab, incoming_args, argsize,
895 incoming_args, 0, OPTAB_LIB_WIDEN);
896#endif
897
898 /* Perform postincrements before actually calling the function. */
899 emit_queue ();
900
04a46d40 901 /* Push a new argument block and copy the arguments. Do not allow
902 the (potential) memcpy call below to interfere with our stack
903 manipulations. */
53800dbe 904 do_pending_stack_adjust ();
04a46d40 905 NO_DEFER_POP;
53800dbe 906
907 /* Save the stack with nonlocal if available */
908#ifdef HAVE_save_stack_nonlocal
909 if (HAVE_save_stack_nonlocal)
910 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
911 else
912#endif
913 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
914
915 /* Push a block of memory onto the stack to store the memory arguments.
916 Save the address in a register, and copy the memory arguments. ??? I
917 haven't figured out how the calling convention macros effect this,
918 but it's likely that the source and/or destination addresses in
919 the block copy will need updating in machine specific ways. */
91b70175 920 dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
53800dbe 921 emit_block_move (gen_rtx_MEM (BLKmode, dest),
922 gen_rtx_MEM (BLKmode, incoming_args),
325d1c45 923 argsize, PARM_BOUNDARY);
53800dbe 924
925 /* Refer to the argument block. */
926 apply_args_size ();
927 arguments = gen_rtx_MEM (BLKmode, arguments);
928
929 /* Walk past the arg-pointer and structure value address. */
930 size = GET_MODE_SIZE (Pmode);
931 if (struct_value_rtx)
932 size += GET_MODE_SIZE (Pmode);
933
934 /* Restore each of the registers previously saved. Make USE insns
935 for each of these registers for use in making the call. */
936 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
937 if ((mode = apply_args_mode[regno]) != VOIDmode)
938 {
939 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
940 if (size % align != 0)
941 size = CEIL (size, align) * align;
942 reg = gen_rtx_REG (mode, regno);
943 emit_move_insn (reg,
944 change_address (arguments, mode,
945 plus_constant (XEXP (arguments, 0),
946 size)));
947
948 use_reg (&call_fusage, reg);
949 size += GET_MODE_SIZE (mode);
950 }
951
952 /* Restore the structure value address unless this is passed as an
953 "invisible" first argument. */
954 size = GET_MODE_SIZE (Pmode);
955 if (struct_value_rtx)
956 {
957 rtx value = gen_reg_rtx (Pmode);
958 emit_move_insn (value,
959 change_address (arguments, Pmode,
960 plus_constant (XEXP (arguments, 0),
961 size)));
962 emit_move_insn (struct_value_rtx, value);
963 if (GET_CODE (struct_value_rtx) == REG)
964 use_reg (&call_fusage, struct_value_rtx);
965 size += GET_MODE_SIZE (Pmode);
966 }
967
968 /* All arguments and registers used for the call are set up by now! */
969 function = prepare_call_address (function, NULL_TREE, &call_fusage, 0);
970
971 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
972 and we don't want to load it into a register as an optimization,
973 because prepare_call_address already did it if it should be done. */
974 if (GET_CODE (function) != SYMBOL_REF)
975 function = memory_address (FUNCTION_MODE, function);
976
977 /* Generate the actual call instruction and save the return value. */
978#ifdef HAVE_untyped_call
979 if (HAVE_untyped_call)
980 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
981 result, result_vector (1, result)));
982 else
983#endif
984#ifdef HAVE_call_value
985 if (HAVE_call_value)
986 {
987 rtx valreg = 0;
988
989 /* Locate the unique return register. It is not possible to
990 express a call that sets more than one return register using
991 call_value; use untyped_call for that. In fact, untyped_call
992 only needs to save the return registers in the given block. */
993 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
994 if ((mode = apply_result_mode[regno]) != VOIDmode)
995 {
996 if (valreg)
997 abort (); /* HAVE_untyped_call required. */
998 valreg = gen_rtx_REG (mode, regno);
999 }
1000
2ed6c343 1001 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1002 gen_rtx_MEM (FUNCTION_MODE, function),
1003 const0_rtx, NULL_RTX, const0_rtx));
1004
1005 emit_move_insn (change_address (result, GET_MODE (valreg),
1006 XEXP (result, 0)),
1007 valreg);
1008 }
1009 else
1010#endif
1011 abort ();
1012
1013 /* Find the CALL insn we just emitted. */
1014 for (call_insn = get_last_insn ();
1015 call_insn && GET_CODE (call_insn) != CALL_INSN;
1016 call_insn = PREV_INSN (call_insn))
1017 ;
1018
1019 if (! call_insn)
1020 abort ();
1021
1022 /* Put the register usage information on the CALL. If there is already
1023 some usage information, put ours at the end. */
1024 if (CALL_INSN_FUNCTION_USAGE (call_insn))
1025 {
1026 rtx link;
1027
1028 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
1029 link = XEXP (link, 1))
1030 ;
1031
1032 XEXP (link, 1) = call_fusage;
1033 }
1034 else
1035 CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1036
1037 /* Restore the stack. */
1038#ifdef HAVE_save_stack_nonlocal
1039 if (HAVE_save_stack_nonlocal)
1040 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1041 else
1042#endif
1043 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1044
04a46d40 1045 OK_DEFER_POP;
1046
53800dbe 1047 /* Return the address of the result block. */
1048 return copy_addr_to_reg (XEXP (result, 0));
1049}
1050
1051/* Perform an untyped return. */
1052
1053static void
1054expand_builtin_return (result)
1055 rtx result;
1056{
1057 int size, align, regno;
1058 enum machine_mode mode;
1059 rtx reg;
1060 rtx call_fusage = 0;
1061
1062 apply_result_size ();
1063 result = gen_rtx_MEM (BLKmode, result);
1064
1065#ifdef HAVE_untyped_return
1066 if (HAVE_untyped_return)
1067 {
1068 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1069 emit_barrier ();
1070 return;
1071 }
1072#endif
1073
1074 /* Restore the return value and note that each value is used. */
1075 size = 0;
1076 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1077 if ((mode = apply_result_mode[regno]) != VOIDmode)
1078 {
1079 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1080 if (size % align != 0)
1081 size = CEIL (size, align) * align;
1082 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1083 emit_move_insn (reg,
1084 change_address (result, mode,
1085 plus_constant (XEXP (result, 0),
1086 size)));
1087
1088 push_to_sequence (call_fusage);
1089 emit_insn (gen_rtx_USE (VOIDmode, reg));
1090 call_fusage = get_insns ();
1091 end_sequence ();
1092 size += GET_MODE_SIZE (mode);
1093 }
1094
1095 /* Put the USE insns before the return. */
1096 emit_insns (call_fusage);
1097
1098 /* Return whatever values was restored by jumping directly to the end
1099 of the function. */
1100 expand_null_return ();
1101}
1102
1103/* Expand a call to __builtin_classify_type with arguments found in
1104 ARGLIST. */
1105static rtx
1106expand_builtin_classify_type (arglist)
1107 tree arglist;
1108{
1109 if (arglist != 0)
1110 {
1111 tree type = TREE_TYPE (TREE_VALUE (arglist));
1112 enum tree_code code = TREE_CODE (type);
1113 if (code == VOID_TYPE)
1114 return GEN_INT (void_type_class);
1115 if (code == INTEGER_TYPE)
1116 return GEN_INT (integer_type_class);
1117 if (code == CHAR_TYPE)
1118 return GEN_INT (char_type_class);
1119 if (code == ENUMERAL_TYPE)
1120 return GEN_INT (enumeral_type_class);
1121 if (code == BOOLEAN_TYPE)
1122 return GEN_INT (boolean_type_class);
1123 if (code == POINTER_TYPE)
1124 return GEN_INT (pointer_type_class);
1125 if (code == REFERENCE_TYPE)
1126 return GEN_INT (reference_type_class);
1127 if (code == OFFSET_TYPE)
1128 return GEN_INT (offset_type_class);
1129 if (code == REAL_TYPE)
1130 return GEN_INT (real_type_class);
1131 if (code == COMPLEX_TYPE)
1132 return GEN_INT (complex_type_class);
1133 if (code == FUNCTION_TYPE)
1134 return GEN_INT (function_type_class);
1135 if (code == METHOD_TYPE)
1136 return GEN_INT (method_type_class);
1137 if (code == RECORD_TYPE)
1138 return GEN_INT (record_type_class);
1139 if (code == UNION_TYPE || code == QUAL_UNION_TYPE)
1140 return GEN_INT (union_type_class);
1141 if (code == ARRAY_TYPE)
1142 {
1143 if (TYPE_STRING_FLAG (type))
1144 return GEN_INT (string_type_class);
1145 else
1146 return GEN_INT (array_type_class);
1147 }
1148 if (code == SET_TYPE)
1149 return GEN_INT (set_type_class);
1150 if (code == FILE_TYPE)
1151 return GEN_INT (file_type_class);
1152 if (code == LANG_TYPE)
1153 return GEN_INT (lang_type_class);
1154 }
1155 return GEN_INT (no_type_class);
1156}
1157
1158/* Expand expression EXP, which is a call to __builtin_constant_p. */
1159static rtx
1160expand_builtin_constant_p (exp)
1161 tree exp;
1162{
1163 tree arglist = TREE_OPERAND (exp, 1);
1164 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
650e4c94 1165 rtx tmp;
53800dbe 1166
1167 if (arglist == 0)
1168 return const0_rtx;
650e4c94 1169 arglist = TREE_VALUE (arglist);
53800dbe 1170
650e4c94 1171 /* We have taken care of the easy cases during constant folding. This
1172 case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE get a
1173 chance to see if it can deduce whether ARGLIST is constant. */
53800dbe 1174
650e4c94 1175 tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
1176 tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
1177 return tmp;
53800dbe 1178}
1179
1180/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1181 Return 0 if a normal call should be emitted rather than expanding the
1182 function in-line. EXP is the expression that is a call to the builtin
1183 function; if convenient, the result should be placed in TARGET.
1184 SUBTARGET may be used as the target for computing one of EXP's operands. */
1185static rtx
1186expand_builtin_mathfn (exp, target, subtarget)
1187 tree exp;
1188 rtx target, subtarget;
1189{
1190 optab builtin_optab;
1191 rtx op0, insns;
1192 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1193 tree arglist = TREE_OPERAND (exp, 1);
1194
1195 if (arglist == 0
1196 /* Arg could be wrong type if user redeclared this fcn wrong. */
1197 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
1198 return 0;
1199
1200 /* Stabilize and compute the argument. */
1201 if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1202 && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1203 {
1204 exp = copy_node (exp);
53800dbe 1205 TREE_OPERAND (exp, 1) = arglist;
f6326164 1206 /* Wrap the computation of the argument in a SAVE_EXPR. That
1207 way, if we need to expand the argument again (as in the
1208 flag_errno_math case below where we cannot directly set
1209 errno), we will not perform side-effects more than once.
1210 Note that here we're mutating the original EXP as well as the
1211 copy; that's the right thing to do in case the original EXP
1212 is expanded later. */
53800dbe 1213 TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
f6326164 1214 arglist = copy_node (arglist);
53800dbe 1215 }
1216 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1217
1218 /* Make a suitable register to place result in. */
1219 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1220
1221 emit_queue ();
1222 start_sequence ();
1223
1224 switch (DECL_FUNCTION_CODE (fndecl))
1225 {
1226 case BUILT_IN_SIN:
1227 builtin_optab = sin_optab; break;
1228 case BUILT_IN_COS:
1229 builtin_optab = cos_optab; break;
1230 case BUILT_IN_FSQRT:
1231 builtin_optab = sqrt_optab; break;
1232 default:
1233 abort ();
1234 }
1235
1236 /* Compute into TARGET.
1237 Set TARGET to wherever the result comes back. */
1238 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
1239 builtin_optab, op0, target, 0);
1240
1241 /* If we were unable to expand via the builtin, stop the
1242 sequence (without outputting the insns) and return 0, causing
1243 a call to the library function. */
1244 if (target == 0)
1245 {
1246 end_sequence ();
1247 return 0;
1248 }
1249
1250 /* Check the results by default. But if flag_fast_math is turned on,
1251 then assume sqrt will always be called with valid arguments. */
1252
1253 if (flag_errno_math && ! flag_fast_math)
1254 {
1255 rtx lab1;
1256
1257 /* Don't define the builtin FP instructions
1258 if your machine is not IEEE. */
1259 if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
1260 abort ();
1261
1262 lab1 = gen_label_rtx ();
1263
1264 /* Test the result; if it is NaN, set errno=EDOM because
1265 the argument was not in the domain. */
1266 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1267 0, 0, lab1);
1268
1269#ifdef TARGET_EDOM
1270 {
1271#ifdef GEN_ERRNO_RTX
1272 rtx errno_rtx = GEN_ERRNO_RTX;
1273#else
1274 rtx errno_rtx
1275 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1276#endif
1277
1278 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1279 }
1280#else
1281 /* We can't set errno=EDOM directly; let the library call do it.
1282 Pop the arguments right away in case the call gets deleted. */
1283 NO_DEFER_POP;
1284 expand_call (exp, target, 0);
1285 OK_DEFER_POP;
1286#endif
1287
1288 emit_label (lab1);
1289 }
1290
1291 /* Output the entire sequence. */
1292 insns = get_insns ();
1293 end_sequence ();
1294 emit_insns (insns);
1295
1296 return target;
1297}
1298
1299/* Expand expression EXP which is a call to the strlen builtin. Return 0
1300 if we failed the caller should emit a normal call, otherwise
1301 try to get the result in TARGET, if convenient (and in mode MODE if that's
1302 convenient). */
f7c44134 1303
53800dbe 1304static rtx
1305expand_builtin_strlen (exp, target, mode)
1306 tree exp;
1307 rtx target;
1308 enum machine_mode mode;
1309{
1310 tree arglist = TREE_OPERAND (exp, 1);
1311 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1312
1313 if (arglist == 0
1314 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1315 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
1316 return 0;
1317 else
1318 {
911c0150 1319 rtx pat;
53800dbe 1320 tree src = TREE_VALUE (arglist);
53800dbe 1321
1322 int align
1323 = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1324
911c0150 1325 rtx result, src_reg, char_rtx, before_strlen;
53800dbe 1326 enum machine_mode insn_mode = value_mode, char_mode;
ef2c4a29 1327 enum insn_code icode = CODE_FOR_nothing;
53800dbe 1328
53800dbe 1329 /* If SRC is not a pointer type, don't do this operation inline. */
1330 if (align == 0)
1331 return 0;
1332
911c0150 1333 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 1334 while (insn_mode != VOIDmode)
1335 {
1336 icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1337 if (icode != CODE_FOR_nothing)
c28ae87f 1338 break;
53800dbe 1339
1340 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1341 }
1342 if (insn_mode == VOIDmode)
1343 return 0;
1344
1345 /* Make a place to write the result of the instruction. */
1346 result = target;
1347 if (! (result != 0
1348 && GET_CODE (result) == REG
1349 && GET_MODE (result) == insn_mode
1350 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1351 result = gen_reg_rtx (insn_mode);
1352
911c0150 1353 /* Make a place to hold the source address. We will not expand
1354 the actual source until we are sure that the expansion will
1355 not fail -- there are trees that cannot be expanded twice. */
1356 src_reg = gen_reg_rtx (Pmode);
53800dbe 1357
911c0150 1358 /* Mark the beginning of the strlen sequence so we can emit the
1359 source operand later. */
1360 before_strlen = get_last_insn();
53800dbe 1361
1362 /* Check the string is readable and has an end. */
1363 if (current_function_check_memory_usage)
2c5d421b 1364 emit_library_call (chkr_check_str_libfunc, LCT_CONST_MAKE_BLOCK,
1365 VOIDmode, 2, src_reg, Pmode,
53800dbe 1366 GEN_INT (MEMORY_USE_RO),
1367 TYPE_MODE (integer_type_node));
1368
1369 char_rtx = const0_rtx;
f7c44134 1370 char_mode = insn_data[(int) icode].operand[2].mode;
1371 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
1372 char_mode))
53800dbe 1373 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1374
911c0150 1375 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1376 char_rtx, GEN_INT (align));
1377 if (! pat)
1378 return 0;
1379 emit_insn (pat);
1380
1381 /* Now that we are assured of success, expand the source. */
1382 start_sequence ();
f508dc8b 1383 pat = memory_address (BLKmode,
f7c44134 1384 expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
911c0150 1385 if (pat != src_reg)
1386 emit_move_insn (src_reg, pat);
1387 pat = gen_sequence ();
1388 end_sequence ();
bceb0d1f 1389
1390 if (before_strlen)
1391 emit_insn_after (pat, before_strlen);
1392 else
1393 emit_insn_before (pat, get_insns ());
53800dbe 1394
1395 /* Return the value in the proper mode for this function. */
1396 if (GET_MODE (result) == value_mode)
911c0150 1397 target = result;
53800dbe 1398 else if (target != 0)
911c0150 1399 convert_move (target, result, 0);
53800dbe 1400 else
911c0150 1401 target = convert_to_mode (value_mode, result, 0);
1402
1403 return target;
53800dbe 1404 }
1405}
1406
17f5ea87 1407/* Expand a call to the strstr builtin. Return 0 if we failed the
1408 caller should emit a normal call, otherwise try to get the result
1409 in TARGET, if convenient (and in mode MODE if that's convenient). */
1410
1411static rtx
1412expand_builtin_strstr (arglist, target, mode)
1413 tree arglist;
1414 rtx target;
1415 enum machine_mode mode;
1416{
1417 if (arglist == 0
1418 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1419 || TREE_CHAIN (arglist) == 0
1420 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE)
1421 return 0;
1422 else
1423 {
1424 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1425 tree len = c_strlen (s2);
1426
1427 if (!len)
1428 return 0;
1429
1430 switch (compare_tree_int (len, 1))
1431 {
1432 case -1: /* length is 0, return s1. */
1433 return expand_expr (s1, target, mode, EXPAND_NORMAL);
1434 case 0: /* length is 1, return strchr(s1, s2[0]). */
1435 {
1436 tree call_expr, fn = built_in_decls[BUILT_IN_STRCHR];
1437
1438 if (!fn)
1439 return 0;
1440 STRIP_NOPS (s2);
1441 if (s2 && TREE_CODE (s2) == ADDR_EXPR)
1442 s2 = TREE_OPERAND (s2, 0);
1443
1444 /* New argument list transforming strstr(s1, s2) to
1445 strchr(s1, s2[0]). */
1446 arglist =
1447 build_tree_list (NULL_TREE,
1448 build_int_2 (TREE_STRING_POINTER (s2)[0], 0));
1449 arglist = tree_cons (NULL_TREE, s1, arglist);
1450 call_expr = build1 (ADDR_EXPR,
1451 build_pointer_type (TREE_TYPE (fn)), fn);
1452 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
1453 call_expr, arglist, NULL_TREE);
1454 TREE_SIDE_EFFECTS (call_expr) = 1;
1455 return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
1456 }
1457 case 1: /* length is greater than 1, really call strstr. */
1458 return 0;
1459 default:
1460 abort();
1461 }
1462 }
1463}
1464
53800dbe 1465/* Expand a call to the memcpy builtin, with arguments in ARGLIST. */
1466static rtx
1467expand_builtin_memcpy (arglist)
1468 tree arglist;
1469{
1470 if (arglist == 0
1471 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1472 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1473 || TREE_CHAIN (arglist) == 0
1474 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1475 != POINTER_TYPE)
1476 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1477 || (TREE_CODE (TREE_TYPE (TREE_VALUE
1478 (TREE_CHAIN (TREE_CHAIN (arglist)))))
1479 != INTEGER_TYPE))
1480 return 0;
1481 else
1482 {
1483 tree dest = TREE_VALUE (arglist);
1484 tree src = TREE_VALUE (TREE_CHAIN (arglist));
1485 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1486
325d1c45 1487 int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1488 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 1489 rtx dest_mem, src_mem, dest_addr, len_rtx;
1490
1491 /* If either SRC or DEST is not a pointer type, don't do
1492 this operation in-line. */
1493 if (src_align == 0 || dest_align == 0)
1494 return 0;
1495
1496 dest_mem = get_memory_rtx (dest);
1497 src_mem = get_memory_rtx (src);
1498 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1499
1500 /* Just copy the rights of SRC to the rights of DEST. */
1501 if (current_function_check_memory_usage)
2c5d421b 1502 emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
1503 VOIDmode, 3, XEXP (dest_mem, 0), Pmode,
53800dbe 1504 XEXP (src_mem, 0), Pmode,
1505 len_rtx, TYPE_MODE (sizetype));
1506
1507 /* Copy word part most expediently. */
1508 dest_addr
1509 = emit_block_move (dest_mem, src_mem, len_rtx,
1510 MIN (src_align, dest_align));
1511
1512 if (dest_addr == 0)
1513 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1514
1515 return dest_addr;
1516 }
1517}
1518
1519/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
1520 if we failed the caller should emit a normal call. */
902de8ed 1521
53800dbe 1522static rtx
1523expand_builtin_strcpy (exp)
1524 tree exp;
1525{
1526 tree arglist = TREE_OPERAND (exp, 1);
1527 rtx result;
1528
1529 if (arglist == 0
1530 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1531 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1532 || TREE_CHAIN (arglist) == 0
902de8ed 1533 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1534 != POINTER_TYPE))
53800dbe 1535 return 0;
1536 else
1537 {
1538 tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
1539
1540 if (len == 0)
1541 return 0;
1542
902de8ed 1543 len = size_binop (PLUS_EXPR, len, ssize_int (1));
53800dbe 1544 chainon (arglist, build_tree_list (NULL_TREE, len));
1545 }
902de8ed 1546
53800dbe 1547 result = expand_builtin_memcpy (arglist);
902de8ed 1548
53800dbe 1549 if (! result)
1550 TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1551 return result;
1552}
1553
1554/* Expand expression EXP, which is a call to the memset builtin. Return 0
1555 if we failed the caller should emit a normal call. */
902de8ed 1556
53800dbe 1557static rtx
1558expand_builtin_memset (exp)
1559 tree exp;
1560{
1561 tree arglist = TREE_OPERAND (exp, 1);
1562
1563 if (arglist == 0
1564 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1565 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1566 || TREE_CHAIN (arglist) == 0
1567 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1568 != INTEGER_TYPE)
1569 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1570 || (INTEGER_TYPE
1571 != (TREE_CODE (TREE_TYPE
1572 (TREE_VALUE
1573 (TREE_CHAIN (TREE_CHAIN (arglist))))))))
1574 return 0;
1575 else
1576 {
1577 tree dest = TREE_VALUE (arglist);
1578 tree val = TREE_VALUE (TREE_CHAIN (arglist));
1579 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1580
325d1c45 1581 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 1582 rtx dest_mem, dest_addr, len_rtx;
1583
1584 /* If DEST is not a pointer type, don't do this
1585 operation in-line. */
1586 if (dest_align == 0)
1587 return 0;
1588
1589 /* If the arguments have side-effects, then we can only evaluate
1590 them at most once. The following code evaluates them twice if
1591 they are not constants because we break out to expand_call
1592 in that case. They can't be constants if they have side-effects
1593 so we can check for that first. Alternatively, we could call
1594 save_expr to make multiple evaluation safe. */
1595 if (TREE_SIDE_EFFECTS (val) || TREE_SIDE_EFFECTS (len))
1596 return 0;
1597
1598 /* If VAL is not 0, don't do this operation in-line. */
1599 if (expand_expr (val, NULL_RTX, VOIDmode, 0) != const0_rtx)
1600 return 0;
1601
53800dbe 1602 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
53800dbe 1603
1604 dest_mem = get_memory_rtx (dest);
1605
1606 /* Just check DST is writable and mark it as readable. */
1607 if (current_function_check_memory_usage)
2c5d421b 1608 emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
1609 VOIDmode, 3, XEXP (dest_mem, 0), Pmode,
53800dbe 1610 len_rtx, TYPE_MODE (sizetype),
1611 GEN_INT (MEMORY_USE_WO),
1612 TYPE_MODE (integer_type_node));
1613
1614
1615 dest_addr = clear_storage (dest_mem, len_rtx, dest_align);
1616
1617 if (dest_addr == 0)
1618 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1619
1620 return dest_addr;
1621 }
1622}
1623
ffc83088 1624/* Expand expression EXP, which is a call to the bzero builtin. Return 0
1625 if we failed the caller should emit a normal call. */
1626static rtx
1627expand_builtin_bzero (exp)
1628 tree exp;
1629{
1630 tree arglist = TREE_OPERAND (exp, 1);
7369e7ba 1631 tree dest, size, newarglist;
1632 rtx result;
ffc83088 1633
1634 if (arglist == 0
1635 /* Arg could be non-pointer if user redeclared this fcn wrong. */
7369e7ba 1636 || TREE_CODE (TREE_TYPE (dest = TREE_VALUE (arglist))) != POINTER_TYPE
ffc83088 1637 || TREE_CHAIN (arglist) == 0
7369e7ba 1638 || (TREE_CODE (TREE_TYPE (size = TREE_VALUE (TREE_CHAIN (arglist))))
ffc83088 1639 != INTEGER_TYPE))
7369e7ba 1640 return NULL_RTX;
ffc83088 1641
7369e7ba 1642 /* New argument list transforming bzero(ptr x, int y) to
1643 memset(ptr x, int 0, size_t y). */
1644
1645 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
1646 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
1647 newarglist = tree_cons (NULL_TREE, dest, newarglist);
ffc83088 1648
7369e7ba 1649 TREE_OPERAND (exp, 1) = newarglist;
1650 result = expand_builtin_memset(exp);
ffc83088 1651
7369e7ba 1652 /* Always restore the original arguments. */
1653 TREE_OPERAND (exp, 1) = arglist;
ffc83088 1654
7369e7ba 1655 return result;
ffc83088 1656}
1657
53800dbe 1658#ifdef HAVE_cmpstrsi
1659/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
1660 ARGLIST is the argument list for this call. Return 0 if we failed and the
1661 caller should emit a normal call, otherwise try to get the result in
1662 TARGET, if convenient. */
1663static rtx
1664expand_builtin_memcmp (exp, arglist, target)
1665 tree exp;
1666 tree arglist;
1667 rtx target;
1668{
1669 /* If we need to check memory accesses, call the library function. */
1670 if (current_function_check_memory_usage)
1671 return 0;
1672
1673 if (arglist == 0
1674 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1675 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1676 || TREE_CHAIN (arglist) == 0
1677 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
1678 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1679 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
1680 return 0;
53800dbe 1681
1682 {
1683 enum machine_mode mode;
1684 tree arg1 = TREE_VALUE (arglist);
1685 tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
1686 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
0cd832f0 1687 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 1688 rtx result;
0cd832f0 1689 rtx insn;
53800dbe 1690
1691 int arg1_align
1692 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1693 int arg2_align
1694 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1695 enum machine_mode insn_mode
6357eaae 1696 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
53800dbe 1697
1698 /* If we don't have POINTER_TYPE, call the function. */
1699 if (arg1_align == 0 || arg2_align == 0)
1700 return 0;
1701
1702 /* Make a place to write the result of the instruction. */
1703 result = target;
1704 if (! (result != 0
1705 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
1706 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1707 result = gen_reg_rtx (insn_mode);
1708
0cd832f0 1709 arg1_rtx = get_memory_rtx (arg1);
1710 arg2_rtx = get_memory_rtx (arg2);
1711 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1712 if (!HAVE_cmpstrsi)
1713 insn = NULL_RTX;
1714 else
1715 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
1716 GEN_INT (MIN (arg1_align, arg2_align)));
1717
1718 if (insn)
1719 emit_insn (insn);
1720 else
2c5d421b 1721 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
0cd832f0 1722 TYPE_MODE (integer_type_node), 3,
1723 XEXP (arg1_rtx, 0), Pmode,
1724 XEXP (arg2_rtx, 0), Pmode,
1725 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
1726 TREE_UNSIGNED (sizetype)),
1727 TYPE_MODE (sizetype));
53800dbe 1728
1729 /* Return the value in the proper mode for this function. */
1730 mode = TYPE_MODE (TREE_TYPE (exp));
1731 if (GET_MODE (result) == mode)
1732 return result;
1733 else if (target != 0)
1734 {
1735 convert_move (target, result, 0);
1736 return target;
1737 }
1738 else
1739 return convert_to_mode (mode, result, 0);
1740 }
1741}
1742
1743/* Expand expression EXP, which is a call to the strcmp builtin. Return 0
1744 if we failed the caller should emit a normal call, otherwise try to get
1745 the result in TARGET, if convenient. */
902de8ed 1746
53800dbe 1747static rtx
1748expand_builtin_strcmp (exp, target)
1749 tree exp;
1750 rtx target;
1751{
1752 tree arglist = TREE_OPERAND (exp, 1);
1753
1754 /* If we need to check memory accesses, call the library function. */
1755 if (current_function_check_memory_usage)
1756 return 0;
1757
1758 if (arglist == 0
1759 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1760 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1761 || TREE_CHAIN (arglist) == 0
902de8ed 1762 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1763 != POINTER_TYPE))
53800dbe 1764 return 0;
902de8ed 1765
1766 else if (! HAVE_cmpstrsi)
53800dbe 1767 return 0;
1768 {
1769 tree arg1 = TREE_VALUE (arglist);
1770 tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
902de8ed 1771 tree len = c_strlen (arg1);
1772 tree len2 = c_strlen (arg2);
53800dbe 1773 rtx result;
902de8ed 1774
53800dbe 1775 if (len)
902de8ed 1776 len = size_binop (PLUS_EXPR, ssize_int (1), len);
1777
53800dbe 1778 if (len2)
902de8ed 1779 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
53800dbe 1780
1781 /* If we don't have a constant length for the first, use the length
1782 of the second, if we know it. We don't require a constant for
1783 this case; some cost analysis could be done if both are available
1784 but neither is constant. For now, assume they're equally cheap.
1785
1786 If both strings have constant lengths, use the smaller. This
1787 could arise if optimization results in strcpy being called with
1788 two fixed strings, or if the code was machine-generated. We should
1789 add some code to the `memcmp' handler below to deal with such
1790 situations, someday. */
902de8ed 1791
53800dbe 1792 if (!len || TREE_CODE (len) != INTEGER_CST)
1793 {
1794 if (len2)
1795 len = len2;
1796 else if (len == 0)
1797 return 0;
1798 }
902de8ed 1799 else if (len2 && TREE_CODE (len2) == INTEGER_CST
1800 && tree_int_cst_lt (len2, len))
1801 len = len2;
53800dbe 1802
1803 chainon (arglist, build_tree_list (NULL_TREE, len));
1804 result = expand_builtin_memcmp (exp, arglist, target);
1805 if (! result)
1806 TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
902de8ed 1807
53800dbe 1808 return result;
1809 }
1810}
1811#endif
1812
a66c9326 1813/* Expand a call to __builtin_saveregs, generating the result in TARGET,
1814 if that's convenient. */
902de8ed 1815
a66c9326 1816rtx
1817expand_builtin_saveregs ()
53800dbe 1818{
a66c9326 1819 rtx val, seq;
53800dbe 1820
1821 /* Don't do __builtin_saveregs more than once in a function.
1822 Save the result of the first call and reuse it. */
1823 if (saveregs_value != 0)
1824 return saveregs_value;
53800dbe 1825
a66c9326 1826 /* When this function is called, it means that registers must be
1827 saved on entry to this function. So we migrate the call to the
1828 first insn of this function. */
1829
1830 start_sequence ();
53800dbe 1831
1832#ifdef EXPAND_BUILTIN_SAVEREGS
a66c9326 1833 /* Do whatever the machine needs done in this case. */
1834 val = EXPAND_BUILTIN_SAVEREGS ();
53800dbe 1835#else
a66c9326 1836 /* ??? We used to try and build up a call to the out of line function,
1837 guessing about what registers needed saving etc. This became much
1838 harder with __builtin_va_start, since we don't have a tree for a
1839 call to __builtin_saveregs to fall back on. There was exactly one
1840 port (i860) that used this code, and I'm unconvinced it could actually
1841 handle the general case. So we no longer try to handle anything
1842 weird and make the backend absorb the evil. */
1843
1844 error ("__builtin_saveregs not supported by this target");
1845 val = const0_rtx;
53800dbe 1846#endif
1847
a66c9326 1848 seq = get_insns ();
1849 end_sequence ();
53800dbe 1850
a66c9326 1851 saveregs_value = val;
53800dbe 1852
a66c9326 1853 /* Put the sequence after the NOTE that starts the function. If this
1854 is inside a SEQUENCE, make the outer-level insn chain current, so
1855 the code is placed at the start of the function. */
1856 push_topmost_sequence ();
1857 emit_insns_after (seq, get_insns ());
1858 pop_topmost_sequence ();
1859
1860 return val;
53800dbe 1861}
1862
1863/* __builtin_args_info (N) returns word N of the arg space info
1864 for the current function. The number and meanings of words
1865 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 1866
53800dbe 1867static rtx
1868expand_builtin_args_info (exp)
1869 tree exp;
1870{
1871 tree arglist = TREE_OPERAND (exp, 1);
1872 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
1873 int *word_ptr = (int *) &current_function_args_info;
1874#if 0
1875 /* These are used by the code below that is if 0'ed away */
1876 int i;
1877 tree type, elts, result;
1878#endif
1879
1880 if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
dda90815 1881 abort ();
53800dbe 1882
1883 if (arglist != 0)
1884 {
1885 tree arg = TREE_VALUE (arglist);
1886 if (TREE_CODE (arg) != INTEGER_CST)
1887 error ("argument of `__builtin_args_info' must be constant");
1888 else
1889 {
1890 int wordnum = TREE_INT_CST_LOW (arg);
1891
1892 if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
1893 error ("argument of `__builtin_args_info' out of range");
1894 else
1895 return GEN_INT (word_ptr[wordnum]);
1896 }
1897 }
1898 else
1899 error ("missing argument in `__builtin_args_info'");
1900
1901 return const0_rtx;
1902
1903#if 0
1904 for (i = 0; i < nwords; i++)
1905 elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
1906
1907 type = build_array_type (integer_type_node,
1908 build_index_type (build_int_2 (nwords, 0)));
1909 result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
1910 TREE_CONSTANT (result) = 1;
1911 TREE_STATIC (result) = 1;
a66c9326 1912 result = build1 (INDIRECT_REF, build_pointer_type (type), result);
53800dbe 1913 TREE_CONSTANT (result) = 1;
1914 return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
1915#endif
1916}
1917
a66c9326 1918/* Expand ARGLIST, from a call to __builtin_next_arg. */
53800dbe 1919static rtx
a66c9326 1920expand_builtin_next_arg (arglist)
1921 tree arglist;
53800dbe 1922{
53800dbe 1923 tree fntype = TREE_TYPE (current_function_decl);
1924
1925 if ((TYPE_ARG_TYPES (fntype) == 0
1926 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1927 == void_type_node))
1928 && ! current_function_varargs)
1929 {
1930 error ("`va_start' used in function with fixed args");
1931 return const0_rtx;
1932 }
1933
1934 if (arglist)
1935 {
1936 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
1937 tree arg = TREE_VALUE (arglist);
1938
1939 /* Strip off all nops for the sake of the comparison. This
1940 is not quite the same as STRIP_NOPS. It does more.
1941 We must also strip off INDIRECT_EXPR for C++ reference
1942 parameters. */
1943 while (TREE_CODE (arg) == NOP_EXPR
1944 || TREE_CODE (arg) == CONVERT_EXPR
1945 || TREE_CODE (arg) == NON_LVALUE_EXPR
1946 || TREE_CODE (arg) == INDIRECT_REF)
1947 arg = TREE_OPERAND (arg, 0);
1948 if (arg != last_parm)
1949 warning ("second parameter of `va_start' not last named argument");
1950 }
1951 else if (! current_function_varargs)
1952 /* Evidently an out of date version of <stdarg.h>; can't validate
1953 va_start's second argument, but can still work as intended. */
1954 warning ("`__builtin_next_arg' called without an argument");
1955
1956 return expand_binop (Pmode, add_optab,
1957 current_function_internal_arg_pointer,
1958 current_function_arg_offset_rtx,
1959 NULL_RTX, 0, OPTAB_LIB_WIDEN);
1960}
1961
a66c9326 1962/* Make it easier for the backends by protecting the valist argument
1963 from multiple evaluations. */
1964
1965static tree
2d47cc32 1966stabilize_va_list (valist, needs_lvalue)
a66c9326 1967 tree valist;
2d47cc32 1968 int needs_lvalue;
a66c9326 1969{
11a61dea 1970 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
a66c9326 1971 {
2d47cc32 1972 if (TREE_SIDE_EFFECTS (valist))
1973 valist = save_expr (valist);
11a61dea 1974
2d47cc32 1975 /* For this case, the backends will be expecting a pointer to
1976 TREE_TYPE (va_list_type_node), but it's possible we've
1977 actually been given an array (an actual va_list_type_node).
1978 So fix it. */
1979 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 1980 {
2d47cc32 1981 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
1982 tree p2 = build_pointer_type (va_list_type_node);
325d1c45 1983
2d47cc32 1984 valist = build1 (ADDR_EXPR, p2, valist);
1985 valist = fold (build1 (NOP_EXPR, p1, valist));
8a15c04a 1986 }
a66c9326 1987 }
11a61dea 1988 else
a66c9326 1989 {
2d47cc32 1990 tree pt;
11a61dea 1991
2d47cc32 1992 if (! needs_lvalue)
1993 {
11a61dea 1994 if (! TREE_SIDE_EFFECTS (valist))
1995 return valist;
2d47cc32 1996
11a61dea 1997 pt = build_pointer_type (va_list_type_node);
2d47cc32 1998 valist = fold (build1 (ADDR_EXPR, pt, valist));
a66c9326 1999 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 2000 }
2d47cc32 2001
11a61dea 2002 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 2003 valist = save_expr (valist);
11a61dea 2004 valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
2005 valist));
a66c9326 2006 }
2007
2008 return valist;
2009}
2010
2011/* The "standard" implementation of va_start: just assign `nextarg' to
2012 the variable. */
2013void
2014std_expand_builtin_va_start (stdarg_p, valist, nextarg)
2015 int stdarg_p ATTRIBUTE_UNUSED;
2016 tree valist;
2017 rtx nextarg;
2018{
2019 tree t;
2020
8a15c04a 2021 if (!stdarg_p)
2022 nextarg = plus_constant (nextarg, -UNITS_PER_WORD);
2023
a66c9326 2024 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2025 make_tree (ptr_type_node, nextarg));
2026 TREE_SIDE_EFFECTS (t) = 1;
2027
2028 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2029}
2030
2031/* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
2032 __builtin_varargs_va_start, depending on STDARG_P. */
2033static rtx
2034expand_builtin_va_start (stdarg_p, arglist)
2035 int stdarg_p;
2036 tree arglist;
2037{
2038 rtx nextarg;
2039 tree chain = arglist, valist;
2040
2041 if (stdarg_p)
2042 nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
2043 else
2044 nextarg = expand_builtin_next_arg (NULL_TREE);
2045
2046 if (TREE_CHAIN (chain))
2047 error ("too many arguments to function `va_start'");
2048
2049 valist = stabilize_va_list (TREE_VALUE (arglist), 1);
2050
2051#ifdef EXPAND_BUILTIN_VA_START
2052 EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
2053#else
2054 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
2055#endif
2056
2057 return const0_rtx;
2058}
2059
a66c9326 2060/* The "standard" implementation of va_arg: read the value from the
2061 current (padded) address and increment by the (padded) size. */
f7c44134 2062
a66c9326 2063rtx
2064std_expand_builtin_va_arg (valist, type)
2065 tree valist, type;
2066{
2067 tree addr_tree, t;
2068 HOST_WIDE_INT align;
2069 HOST_WIDE_INT rounded_size;
2070 rtx addr;
2071
2072 /* Compute the rounded size of the type. */
2073 align = PARM_BOUNDARY / BITS_PER_UNIT;
7102dbcc 2074 rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
a66c9326 2075
2076 /* Get AP. */
2077 addr_tree = valist;
726e2588 2078 if (PAD_VARARGS_DOWN)
a66c9326 2079 {
2080 /* Small args are padded downward. */
2081
2082 HOST_WIDE_INT adj;
2083 adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
2084 if (rounded_size > align)
2085 adj = rounded_size;
2086
2087 addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
2088 build_int_2 (rounded_size - adj, 0));
2089 }
2090
2091 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2092 addr = copy_to_reg (addr);
2093
2094 /* Compute new value for AP. */
2095 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2096 build (PLUS_EXPR, TREE_TYPE (valist), valist,
2097 build_int_2 (rounded_size, 0)));
2098 TREE_SIDE_EFFECTS (t) = 1;
2099 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2100
2101 return addr;
2102}
2103
2104/* Expand __builtin_va_arg, which is not really a builtin function, but
2105 a very special sort of operator. */
f7c44134 2106
a66c9326 2107rtx
2108expand_builtin_va_arg (valist, type)
2109 tree valist, type;
2110{
2111 rtx addr, result;
6cd005c9 2112 tree promoted_type, want_va_type, have_va_type;
a66c9326 2113
6cd005c9 2114 /* Verify that valist is of the proper type. */
2115
2116 want_va_type = va_list_type_node;
2117 have_va_type = TREE_TYPE (valist);
2118 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
2119 {
2120 /* If va_list is an array type, the argument may have decayed
2121 to a pointer type, e.g. by being passed to another function.
2122 In that case, unwrap both types so that we can compare the
2123 underlying records. */
2124 if (TREE_CODE (have_va_type) == ARRAY_TYPE
2125 || TREE_CODE (have_va_type) == POINTER_TYPE)
2126 {
2127 want_va_type = TREE_TYPE (want_va_type);
2128 have_va_type = TREE_TYPE (have_va_type);
2129 }
2130 }
2131 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
a66c9326 2132 {
e94026da 2133 error ("first argument to `va_arg' not of type `va_list'");
2134 addr = const0_rtx;
2135 }
6cd005c9 2136
2137 /* Generate a diagnostic for requesting data of a type that cannot
2138 be passed through `...' due to type promotion at the call site. */
e94026da 2139 else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
2140 {
01ce7a1b 2141 const char *name = "<anonymous type>", *pname = 0;
e94026da 2142 static int gave_help;
2143
2144 if (TYPE_NAME (type))
2145 {
2146 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
2147 name = IDENTIFIER_POINTER (TYPE_NAME (type));
2148 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
2149 && DECL_NAME (TYPE_NAME (type)))
2150 name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
2151 }
2152 if (TYPE_NAME (promoted_type))
2153 {
2154 if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
2155 pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
2156 else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
2157 && DECL_NAME (TYPE_NAME (promoted_type)))
2158 pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
2159 }
2160
2161 error ("`%s' is promoted to `%s' when passed through `...'", name, pname);
2162 if (! gave_help)
2163 {
2164 gave_help = 1;
2165 error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name);
2166 }
2167
a66c9326 2168 addr = const0_rtx;
2169 }
2170 else
2171 {
2172 /* Make it easier for the backends by protecting the valist argument
2173 from multiple evaluations. */
2174 valist = stabilize_va_list (valist, 0);
2175
2176#ifdef EXPAND_BUILTIN_VA_ARG
2177 addr = EXPAND_BUILTIN_VA_ARG (valist, type);
2178#else
2179 addr = std_expand_builtin_va_arg (valist, type);
2180#endif
2181 }
2182
2183 result = gen_rtx_MEM (TYPE_MODE (type), addr);
2184 MEM_ALIAS_SET (result) = get_varargs_alias_set ();
2185
2186 return result;
2187}
2188
2189/* Expand ARGLIST, from a call to __builtin_va_end. */
f7c44134 2190
a66c9326 2191static rtx
2192expand_builtin_va_end (arglist)
8a15c04a 2193 tree arglist;
a66c9326 2194{
8a15c04a 2195 tree valist = TREE_VALUE (arglist);
2196
a66c9326 2197#ifdef EXPAND_BUILTIN_VA_END
a66c9326 2198 valist = stabilize_va_list (valist, 0);
2199 EXPAND_BUILTIN_VA_END(arglist);
8a15c04a 2200#else
2201 /* Evaluate for side effects, if needed. I hate macros that don't
2202 do that. */
2203 if (TREE_SIDE_EFFECTS (valist))
2204 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 2205#endif
2206
2207 return const0_rtx;
2208}
2209
2210/* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a
2211 builtin rather than just as an assignment in stdarg.h because of the
2212 nastiness of array-type va_list types. */
f7c44134 2213
a66c9326 2214static rtx
2215expand_builtin_va_copy (arglist)
2216 tree arglist;
2217{
2218 tree dst, src, t;
2219
2220 dst = TREE_VALUE (arglist);
2221 src = TREE_VALUE (TREE_CHAIN (arglist));
2222
2223 dst = stabilize_va_list (dst, 1);
2224 src = stabilize_va_list (src, 0);
2225
2226 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
2227 {
2228 t = build (MODIFY_EXPR, va_list_type_node, dst, src);
2229 TREE_SIDE_EFFECTS (t) = 1;
2230 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2231 }
2232 else
2233 {
11a61dea 2234 rtx dstb, srcb, size;
2235
2236 /* Evaluate to pointers. */
2237 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
2238 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
2239 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
2240 VOIDmode, EXPAND_NORMAL);
2241
2242 /* "Dereference" to BLKmode memories. */
2243 dstb = gen_rtx_MEM (BLKmode, dstb);
2244 MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
2245 srcb = gen_rtx_MEM (BLKmode, srcb);
2246 MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
2247
2248 /* Copy. */
325d1c45 2249 emit_block_move (dstb, srcb, size, TYPE_ALIGN (va_list_type_node));
a66c9326 2250 }
2251
2252 return const0_rtx;
2253}
2254
53800dbe 2255/* Expand a call to one of the builtin functions __builtin_frame_address or
2256 __builtin_return_address. */
2257static rtx
2258expand_builtin_frame_address (exp)
2259 tree exp;
2260{
2261 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2262 tree arglist = TREE_OPERAND (exp, 1);
2263
2264 /* The argument must be a nonnegative integer constant.
2265 It counts the number of frames to scan up the stack.
2266 The value is the return address saved in that frame. */
2267 if (arglist == 0)
2268 /* Warning about missing arg was already issued. */
2269 return const0_rtx;
2270 else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST
2271 || tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
2272 {
2273 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2274 error ("invalid arg to `__builtin_frame_address'");
2275 else
2276 error ("invalid arg to `__builtin_return_address'");
2277 return const0_rtx;
2278 }
2279 else
2280 {
2281 rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
2282 TREE_INT_CST_LOW (TREE_VALUE (arglist)),
2283 hard_frame_pointer_rtx);
2284
2285 /* Some ports cannot access arbitrary stack frames. */
2286 if (tem == NULL)
2287 {
2288 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2289 warning ("unsupported arg to `__builtin_frame_address'");
2290 else
2291 warning ("unsupported arg to `__builtin_return_address'");
2292 return const0_rtx;
2293 }
2294
2295 /* For __builtin_frame_address, return what we've got. */
2296 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2297 return tem;
2298
2299 if (GET_CODE (tem) != REG
2300 && ! CONSTANT_P (tem))
2301 tem = copy_to_mode_reg (Pmode, tem);
2302 return tem;
2303 }
2304}
2305
2306/* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
2307 we failed and the caller should emit a normal call, otherwise try to get
2308 the result in TARGET, if convenient. */
2309static rtx
2310expand_builtin_alloca (arglist, target)
2311 tree arglist;
2312 rtx target;
2313{
2314 rtx op0;
2315
2316 if (arglist == 0
2317 /* Arg could be non-integer if user redeclared this fcn wrong. */
2318 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2319 return 0;
2320
2321 /* Compute the argument. */
2322 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
2323
2324 /* Allocate the desired space. */
2325 return allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
2326}
2327
2328/* Expand a call to the ffs builtin. The arguments are in ARGLIST.
2329 Return 0 if a normal call should be emitted rather than expanding the
2330 function in-line. If convenient, the result should be placed in TARGET.
2331 SUBTARGET may be used as the target for computing one of EXP's operands. */
2332static rtx
2333expand_builtin_ffs (arglist, target, subtarget)
2334 tree arglist;
2335 rtx target, subtarget;
2336{
2337 rtx op0;
2338 if (arglist == 0
2339 /* Arg could be non-integer if user redeclared this fcn wrong. */
2340 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2341 return 0;
2342
2343 /* Compute the argument. */
2344 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
2345 /* Compute ffs, into TARGET if possible.
2346 Set TARGET to wherever the result comes back. */
2347 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
2348 ffs_optab, op0, target, 1);
2349 if (target == 0)
2350 abort ();
2351 return target;
2352}
89cfe6e5 2353
df94cd3b 2354/* If the string passed to fputs is a constant and is one character
2355 long, we attempt to transform this call into __builtin_fputc(). */
2356static rtx
2357expand_builtin_fputs (arglist, ignore)
2358 tree arglist;
2359 int ignore;
2360{
ce1b14f4 2361 tree call_expr, len, fn, fn_fputc = built_in_decls[BUILT_IN_FPUTC],
2362 fn_fwrite = built_in_decls[BUILT_IN_FWRITE];
df94cd3b 2363
2364 /* If the return value is used, or the replacement _DECL isn't
2365 initialized, don't do the transformation. */
ce1b14f4 2366 if (!ignore || !fn_fputc || !fn_fwrite)
df94cd3b 2367 return 0;
2368
2369 /* Verify the arguments in the original call. */
2370 if (arglist == 0
2371 || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2372 || TREE_CHAIN (arglist) == 0
2373 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
2374 != POINTER_TYPE))
2375 return 0;
2376
ce1b14f4 2377 /* Get the length of the string passed to fputs. If the length
2378 can't be determined, punt. */
2379 if (!(len = c_strlen (TREE_VALUE (arglist))))
df94cd3b 2380 return 0;
2381
ce1b14f4 2382 switch (compare_tree_int (len, 1))
2383 {
2384 case -1: /* length is 0, delete the call entirely . */
6d42b7e4 2385 {
2386 /* Evaluate and ignore the argument in case it has
2387 side-effects. */
2388 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
2389 VOIDmode, EXPAND_NORMAL);
2390 return const0_rtx;
2391 }
ce1b14f4 2392 case 0: /* length is 1, call fputc. */
2393 {
2394 tree stripped_string = TREE_VALUE (arglist);
df94cd3b 2395
ce1b14f4 2396 STRIP_NOPS (stripped_string);
2397 if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
2398 stripped_string = TREE_OPERAND (stripped_string, 0);
2399
2400 /* New argument list transforming fputs(string, stream) to
2401 fputc(string[0], stream). */
2402 arglist =
2403 build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
2404 arglist =
2405 tree_cons (NULL_TREE,
2406 build_int_2 (TREE_STRING_POINTER (stripped_string)[0], 0),
2407 arglist);
2408 fn = fn_fputc;
2409 break;
2410 }
2411 case 1: /* length is greater than 1, call fwrite. */
2412 {
2413 tree string_arg = TREE_VALUE (arglist);
2414
2415 /* New argument list transforming fputs(string, stream) to
2416 fwrite(string, 1, len, stream). */
2417 arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
2418 arglist = tree_cons (NULL_TREE, len, arglist);
2419 arglist = tree_cons (NULL_TREE, integer_one_node, arglist);
2420 arglist = tree_cons (NULL_TREE, string_arg, arglist);
2421 fn = fn_fwrite;
2422 break;
2423 }
2424 default:
2425 abort();
2426 }
df94cd3b 2427
df94cd3b 2428 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
2429 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
ce1b14f4 2430 call_expr, arglist, NULL_TREE);
df94cd3b 2431 TREE_SIDE_EFFECTS (call_expr) = 1;
3311f67b 2432 return expand_expr (call_expr, (ignore ? const0_rtx : NULL_RTX),
2433 VOIDmode, EXPAND_NORMAL);
2434}
2435
89cfe6e5 2436/* Expand a call to __builtin_expect. We return our argument and
2437 emit a NOTE_INSN_EXPECTED_VALUE note. */
2438
2439static rtx
2440expand_builtin_expect (arglist, target)
2441 tree arglist;
2442 rtx target;
2443{
2444 tree exp, c;
2445 rtx note, rtx_c;
2446
2447 if (arglist == NULL_TREE
2448 || TREE_CHAIN (arglist) == NULL_TREE)
2449 return const0_rtx;
2450 exp = TREE_VALUE (arglist);
2451 c = TREE_VALUE (TREE_CHAIN (arglist));
2452
2453 if (TREE_CODE (c) != INTEGER_CST)
2454 {
2455 error ("second arg to `__builtin_expect' must be a constant");
2456 c = integer_zero_node;
2457 }
2458
2459 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
2460
2461 /* Don't bother with expected value notes for integral constants. */
2462 if (GET_CODE (target) != CONST_INT)
2463 {
2464 /* We do need to force this into a register so that we can be
2465 moderately sure to be able to correctly interpret the branch
2466 condition later. */
2467 target = force_reg (GET_MODE (target), target);
2468
2469 rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
2470
2471 note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
2472 NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
2473 }
2474
2475 return target;
2476}
53800dbe 2477\f
2478/* Expand an expression EXP that calls a built-in function,
2479 with result going to TARGET if that's convenient
2480 (and in mode MODE if that's convenient).
2481 SUBTARGET may be used as the target for computing one of EXP's operands.
2482 IGNORE is nonzero if the value is to be ignored. */
2483
2484rtx
2485expand_builtin (exp, target, subtarget, mode, ignore)
2486 tree exp;
2487 rtx target;
2488 rtx subtarget;
2489 enum machine_mode mode;
2490 int ignore;
2491{
2492 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2493 tree arglist = TREE_OPERAND (exp, 1);
2494 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
2495
8305149e 2496#ifdef MD_EXPAND_BUILTIN
2497 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
2498 return MD_EXPAND_BUILTIN (exp, target, subtarget, mode, ignore);
2499#endif
2500
53800dbe 2501 /* When not optimizing, generate calls to library functions for a certain
2502 set of builtins. */
2503 if (! optimize && ! CALLED_AS_BUILT_IN (fndecl)
2504 && (fcode == BUILT_IN_SIN || fcode == BUILT_IN_COS
2505 || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
2506 || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
ffc83088 2507 || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
53800dbe 2508 || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
17f5ea87 2509 || fcode == BUILT_IN_STRSTR
df94cd3b 2510 || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
3311f67b 2511 || fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS
2512 || fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC
ce1b14f4 2513 || fcode == BUILT_IN_FPUTS || fcode == BUILT_IN_FWRITE))
53800dbe 2514 return expand_call (exp, target, ignore);
2515
2516 switch (fcode)
2517 {
2518 case BUILT_IN_ABS:
2519 case BUILT_IN_LABS:
5b8f6e0a 2520 case BUILT_IN_LLABS:
53800dbe 2521 case BUILT_IN_FABS:
2522 /* build_function_call changes these into ABS_EXPR. */
2523 abort ();
2524
2525 case BUILT_IN_SIN:
2526 case BUILT_IN_COS:
2527 /* Treat these like sqrt, but only if the user asks for them. */
2528 if (! flag_fast_math)
2529 break;
2530 case BUILT_IN_FSQRT:
2531 target = expand_builtin_mathfn (exp, target, subtarget);
2532 if (target)
2533 return target;
2534 break;
2535
2536 case BUILT_IN_FMOD:
2537 break;
2538
2539 case BUILT_IN_APPLY_ARGS:
2540 return expand_builtin_apply_args ();
2541
2542 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
2543 FUNCTION with a copy of the parameters described by
2544 ARGUMENTS, and ARGSIZE. It returns a block of memory
2545 allocated on the stack into which is stored all the registers
2546 that might possibly be used for returning the result of a
2547 function. ARGUMENTS is the value returned by
2548 __builtin_apply_args. ARGSIZE is the number of bytes of
2549 arguments that must be copied. ??? How should this value be
2550 computed? We'll also need a safe worst case value for varargs
2551 functions. */
2552 case BUILT_IN_APPLY:
2553 if (arglist == 0
2554 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2555 || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
2556 || TREE_CHAIN (arglist) == 0
2557 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
2558 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2559 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
2560 return const0_rtx;
2561 else
2562 {
2563 int i;
2564 tree t;
2565 rtx ops[3];
2566
2567 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
2568 ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
2569
2570 return expand_builtin_apply (ops[0], ops[1], ops[2]);
2571 }
2572
2573 /* __builtin_return (RESULT) causes the function to return the
2574 value described by RESULT. RESULT is address of the block of
2575 memory returned by __builtin_apply. */
2576 case BUILT_IN_RETURN:
2577 if (arglist
2578 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2579 && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
2580 expand_builtin_return (expand_expr (TREE_VALUE (arglist),
2581 NULL_RTX, VOIDmode, 0));
2582 return const0_rtx;
2583
2584 case BUILT_IN_SAVEREGS:
a66c9326 2585 return expand_builtin_saveregs ();
53800dbe 2586
2587 case BUILT_IN_ARGS_INFO:
2588 return expand_builtin_args_info (exp);
2589
2590 /* Return the address of the first anonymous stack arg. */
2591 case BUILT_IN_NEXT_ARG:
a66c9326 2592 return expand_builtin_next_arg (arglist);
53800dbe 2593
2594 case BUILT_IN_CLASSIFY_TYPE:
2595 return expand_builtin_classify_type (arglist);
2596
2597 case BUILT_IN_CONSTANT_P:
2598 return expand_builtin_constant_p (exp);
2599
2600 case BUILT_IN_FRAME_ADDRESS:
2601 case BUILT_IN_RETURN_ADDRESS:
2602 return expand_builtin_frame_address (exp);
2603
2604 /* Returns the address of the area where the structure is returned.
2605 0 otherwise. */
2606 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
2607 if (arglist != 0
2608 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
2609 || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
2610 return const0_rtx;
2611 else
2612 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
2613
2614 case BUILT_IN_ALLOCA:
2615 target = expand_builtin_alloca (arglist, target);
2616 if (target)
2617 return target;
2618 break;
2619
2620 case BUILT_IN_FFS:
bdc5170d 2621 target = expand_builtin_ffs (arglist, target, subtarget);
53800dbe 2622 if (target)
2623 return target;
2624 break;
2625
2626 case BUILT_IN_STRLEN:
2627 target = expand_builtin_strlen (exp, target, mode);
2628 if (target)
2629 return target;
2630 break;
2631
2632 case BUILT_IN_STRCPY:
2633 target = expand_builtin_strcpy (exp);
2634 if (target)
2635 return target;
2636 break;
2637
17f5ea87 2638 case BUILT_IN_STRSTR:
2639 target = expand_builtin_strstr (arglist, target, mode);
2640 if (target)
2641 return target;
2642 break;
2643
53800dbe 2644 case BUILT_IN_MEMCPY:
2645 target = expand_builtin_memcpy (arglist);
2646 if (target)
2647 return target;
2648 break;
2649
2650 case BUILT_IN_MEMSET:
2651 target = expand_builtin_memset (exp);
2652 if (target)
2653 return target;
2654 break;
2655
ffc83088 2656 case BUILT_IN_BZERO:
2657 target = expand_builtin_bzero (exp);
2658 if (target)
2659 return target;
2660 break;
2661
53800dbe 2662/* These comparison functions need an instruction that returns an actual
2663 index. An ordinary compare that just sets the condition codes
2664 is not enough. */
2665#ifdef HAVE_cmpstrsi
2666 case BUILT_IN_STRCMP:
2667 target = expand_builtin_strcmp (exp, target);
2668 if (target)
2669 return target;
2670 break;
2671
071f1696 2672 case BUILT_IN_BCMP:
53800dbe 2673 case BUILT_IN_MEMCMP:
2674 target = expand_builtin_memcmp (exp, arglist, target);
2675 if (target)
2676 return target;
2677 break;
2678#else
2679 case BUILT_IN_STRCMP:
071f1696 2680 case BUILT_IN_BCMP:
53800dbe 2681 case BUILT_IN_MEMCMP:
2682 break;
2683#endif
2684
2685 case BUILT_IN_SETJMP:
2686 if (arglist == 0
2687 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2688 break;
2689 else
2690 {
2691 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2692 VOIDmode, 0);
2693 rtx lab = gen_label_rtx ();
2694 rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab);
2695 emit_label (lab);
2696 return ret;
2697 }
2698
2699 /* __builtin_longjmp is passed a pointer to an array of five words.
2700 It's similar to the C library longjmp function but works with
2701 __builtin_setjmp above. */
2702 case BUILT_IN_LONGJMP:
2703 if (arglist == 0 || TREE_CHAIN (arglist) == 0
2704 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2705 break;
2706 else
2707 {
2708 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2709 VOIDmode, 0);
2710 rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
2711 NULL_RTX, VOIDmode, 0);
2712
2713 if (value != const1_rtx)
2714 {
2715 error ("__builtin_longjmp second argument must be 1");
2716 return const0_rtx;
2717 }
2718
2719 expand_builtin_longjmp (buf_addr, value);
2720 return const0_rtx;
2721 }
2722
2723 case BUILT_IN_TRAP:
2724#ifdef HAVE_trap
2725 if (HAVE_trap)
2726 emit_insn (gen_trap ());
2727 else
2728#endif
2729 error ("__builtin_trap not supported by this target");
2730 emit_barrier ();
2731 return const0_rtx;
2732
3311f67b 2733 case BUILT_IN_PUTCHAR:
2734 case BUILT_IN_PUTS:
df94cd3b 2735 case BUILT_IN_FPUTC:
ce1b14f4 2736 case BUILT_IN_FWRITE:
17f5ea87 2737 case BUILT_IN_STRCHR:
df94cd3b 2738 break;
2739
2740 case BUILT_IN_FPUTS:
2741 target = expand_builtin_fputs (arglist, ignore);
2742 if (target)
2743 return target;
2744 break;
2745
53800dbe 2746 /* Various hooks for the DWARF 2 __throw routine. */
2747 case BUILT_IN_UNWIND_INIT:
2748 expand_builtin_unwind_init ();
2749 return const0_rtx;
2750 case BUILT_IN_DWARF_CFA:
2751 return virtual_cfa_rtx;
2752#ifdef DWARF2_UNWIND_INFO
2753 case BUILT_IN_DWARF_FP_REGNUM:
2754 return expand_builtin_dwarf_fp_regnum ();
695e919b 2755 case BUILT_IN_INIT_DWARF_REG_SIZES:
2756 expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
2757 return const0_rtx;
53800dbe 2758#endif
2759 case BUILT_IN_FROB_RETURN_ADDR:
2760 return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
2761 case BUILT_IN_EXTRACT_RETURN_ADDR:
2762 return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
2763 case BUILT_IN_EH_RETURN:
2764 expand_builtin_eh_return (TREE_VALUE (arglist),
2765 TREE_VALUE (TREE_CHAIN (arglist)),
2766 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
2767 return const0_rtx;
a66c9326 2768 case BUILT_IN_VARARGS_START:
2769 return expand_builtin_va_start (0, arglist);
2770 case BUILT_IN_STDARG_START:
2771 return expand_builtin_va_start (1, arglist);
2772 case BUILT_IN_VA_END:
2773 return expand_builtin_va_end (arglist);
2774 case BUILT_IN_VA_COPY:
2775 return expand_builtin_va_copy (arglist);
89cfe6e5 2776 case BUILT_IN_EXPECT:
2777 return expand_builtin_expect (arglist, target);
53800dbe 2778
2779 default: /* just do library call, if unknown builtin */
2780 error ("built-in function `%s' not currently supported",
2781 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
2782 }
2783
2784 /* The switch statement above can drop through to cause the function
2785 to be called normally. */
2786 return expand_call (exp, target, ignore);
2787}
650e4c94 2788
2789/* Fold a call to __builtin_constant_p, if we know it will evaluate to a
2790 constant. ARGLIST is the argument list of the call. */
2791
2792static tree
2793fold_builtin_constant_p (arglist)
2794 tree arglist;
2795{
2796 if (arglist == 0)
2797 return 0;
2798
2799 arglist = TREE_VALUE (arglist);
2800
2801 /* We return 1 for a numeric type that's known to be a constant
2802 value at compile-time or for an aggregate type that's a
2803 literal constant. */
2804 STRIP_NOPS (arglist);
2805
2806 /* If we know this is a constant, emit the constant of one. */
2807 if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
2808 || (TREE_CODE (arglist) == CONSTRUCTOR
2809 && TREE_CONSTANT (arglist))
2810 || (TREE_CODE (arglist) == ADDR_EXPR
2811 && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
2812 return integer_one_node;
2813
2814 /* If we aren't going to be running CSE or this expression
2815 has side effects, show we don't know it to be a constant.
2816 Likewise if it's a pointer or aggregate type since in those
2817 case we only want literals, since those are only optimized
2818 when generating RTL, not later. */
2819 if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
2820 || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
2821 || POINTER_TYPE_P (TREE_TYPE (arglist)))
2822 return integer_zero_node;
2823
2824 return 0;
2825}
2826
2827/* Used by constant folding to eliminate some builtin calls early. EXP is
2828 the CALL_EXPR of a call to a builtin function. */
2829
2830tree
2831fold_builtin (exp)
2832 tree exp;
2833{
2834 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2835 tree arglist = TREE_OPERAND (exp, 1);
2836 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
2837
2838 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
2839 return 0;
2840
2841 switch (fcode)
2842 {
2843 case BUILT_IN_CONSTANT_P:
2844 return fold_builtin_constant_p (arglist);
2845
2846 case BUILT_IN_STRLEN:
2847 if (arglist != 0
2848 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2849 && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
2850 {
2851 tree len = c_strlen (TREE_VALUE (arglist));
2852 if (len != 0)
2853 return len;
2854 }
2855 break;
2856
2857 default:
2858 break;
2859 }
2860
2861 return 0;
2862}