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