Deleted Added
full compact
expr.c (72562) expr.c (74473)
1/* Convert tree expression to rtl instructions, for GNU compiler.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001 Free Software Foundation, Inc.
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

--- 178 unchanged lines hidden (view full) ---

187static tree string_constant PROTO((tree, tree *));
188static tree c_strlen PROTO((tree));
189static rtx get_memory_rtx PROTO((tree));
190static rtx expand_builtin PROTO((tree, rtx, rtx,
191 enum machine_mode, int));
192static int apply_args_size PROTO((void));
193static int apply_result_size PROTO((void));
194static rtx result_vector PROTO((int, rtx));
1/* Convert tree expression to rtl instructions, for GNU compiler.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001 Free Software Foundation, Inc.
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

--- 178 unchanged lines hidden (view full) ---

187static tree string_constant PROTO((tree, tree *));
188static tree c_strlen PROTO((tree));
189static rtx get_memory_rtx PROTO((tree));
190static rtx expand_builtin PROTO((tree, rtx, rtx,
191 enum machine_mode, int));
192static int apply_args_size PROTO((void));
193static int apply_result_size PROTO((void));
194static rtx result_vector PROTO((int, rtx));
195static rtx expand_builtin_setjmp PROTO((tree, rtx));
196static rtx expand_builtin_apply_args PROTO((void));
197static rtx expand_builtin_apply PROTO((rtx, rtx, rtx));
198static void expand_builtin_return PROTO((rtx));
199static rtx expand_increment PROTO((tree, int, int));
200static void preexpand_calls PROTO((tree));
201static void do_jump_by_parts_greater PROTO((tree, int, rtx, rtx));
202static void do_jump_by_parts_equality PROTO((tree, rtx, rtx));
203static void do_jump_for_compare PROTO((rtx, rtx, rtx));

--- 8336 unchanged lines hidden (view full) ---

8540#else
8541 tem = memory_address (Pmode,
8542 plus_constant (tem, GET_MODE_SIZE (Pmode)));
8543 tem = gen_rtx_MEM (Pmode, tem);
8544#endif
8545 return tem;
8546}
8547
195static rtx expand_builtin_apply_args PROTO((void));
196static rtx expand_builtin_apply PROTO((rtx, rtx, rtx));
197static void expand_builtin_return PROTO((rtx));
198static rtx expand_increment PROTO((tree, int, int));
199static void preexpand_calls PROTO((tree));
200static void do_jump_by_parts_greater PROTO((tree, int, rtx, rtx));
201static void do_jump_by_parts_equality PROTO((tree, rtx, rtx));
202static void do_jump_for_compare PROTO((rtx, rtx, rtx));

--- 8336 unchanged lines hidden (view full) ---

8539#else
8540 tem = memory_address (Pmode,
8541 plus_constant (tem, GET_MODE_SIZE (Pmode)));
8542 tem = gen_rtx_MEM (Pmode, tem);
8543#endif
8544 return tem;
8545}
8546
8548/* Construct the leading half of a __builtin_setjmp call. Control will
8549 return to RECEIVER_LABEL. This is used directly by sjlj exception
8550 handling code. */
8547/* __builtin_setjmp is passed a pointer to an array of five words (not
8548 all will be used on all machines). It operates similarly to the C
8549 library function of the same name, but is more efficient. Much of
8550 the code below (and for longjmp) is copied from the handling of
8551 non-local gotos.
8551
8552
8552void
8553expand_builtin_setjmp_setup (buf_addr, receiver_label)
8553 NOTE: This is intended for use by GNAT and the exception handling
8554 scheme in the compiler and will only work in the method used by
8555 them. */
8556
8557rtx
8558expand_builtin_setjmp (buf_addr, target, first_label, next_label)
8554 rtx buf_addr;
8559 rtx buf_addr;
8555 rtx receiver_label;
8560 rtx target;
8561 rtx first_label, next_label;
8556{
8562{
8563 rtx lab1 = gen_label_rtx ();
8557 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
8564 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
8565 enum machine_mode value_mode;
8558 rtx stack_save;
8559
8566 rtx stack_save;
8567
8568 value_mode = TYPE_MODE (integer_type_node);
8569
8560#ifdef POINTERS_EXTEND_UNSIGNED
8561 buf_addr = convert_memory_address (Pmode, buf_addr);
8562#endif
8563
8564 buf_addr = force_reg (Pmode, buf_addr);
8565
8570#ifdef POINTERS_EXTEND_UNSIGNED
8571 buf_addr = convert_memory_address (Pmode, buf_addr);
8572#endif
8573
8574 buf_addr = force_reg (Pmode, buf_addr);
8575
8576 if (target == 0 || GET_CODE (target) != REG
8577 || REGNO (target) < FIRST_PSEUDO_REGISTER)
8578 target = gen_reg_rtx (value_mode);
8579
8566 emit_queue ();
8567
8580 emit_queue ();
8581
8568 /* We store the frame pointer and the address of receiver_label in
8569 the buffer and use the rest of it for the stack save area, which
8570 is machine-dependent. */
8582 /* We store the frame pointer and the address of lab1 in the buffer
8583 and use the rest of it for the stack save area, which is
8584 machine-dependent. */
8571
8572#ifndef BUILTIN_SETJMP_FRAME_VALUE
8573#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
8574#endif
8575
8576 emit_move_insn (gen_rtx_MEM (Pmode, buf_addr),
8577 BUILTIN_SETJMP_FRAME_VALUE);
8578 emit_move_insn (validize_mem
8579 (gen_rtx_MEM (Pmode,
8580 plus_constant (buf_addr,
8581 GET_MODE_SIZE (Pmode)))),
8585
8586#ifndef BUILTIN_SETJMP_FRAME_VALUE
8587#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
8588#endif
8589
8590 emit_move_insn (gen_rtx_MEM (Pmode, buf_addr),
8591 BUILTIN_SETJMP_FRAME_VALUE);
8592 emit_move_insn (validize_mem
8593 (gen_rtx_MEM (Pmode,
8594 plus_constant (buf_addr,
8595 GET_MODE_SIZE (Pmode)))),
8582 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
8596 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1)));
8583
8584 stack_save = gen_rtx_MEM (sa_mode,
8585 plus_constant (buf_addr,
8586 2 * GET_MODE_SIZE (Pmode)));
8587 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
8588
8589 /* If there is further processing to do, do it. */
8590#ifdef HAVE_builtin_setjmp_setup
8591 if (HAVE_builtin_setjmp_setup)
8592 emit_insn (gen_builtin_setjmp_setup (buf_addr));
8593#endif
8594
8597
8598 stack_save = gen_rtx_MEM (sa_mode,
8599 plus_constant (buf_addr,
8600 2 * GET_MODE_SIZE (Pmode)));
8601 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
8602
8603 /* If there is further processing to do, do it. */
8604#ifdef HAVE_builtin_setjmp_setup
8605 if (HAVE_builtin_setjmp_setup)
8606 emit_insn (gen_builtin_setjmp_setup (buf_addr));
8607#endif
8608
8595 /* Tell optimize_save_area_alloca that extra work is going to
8596 need to go on during alloca. */
8597 current_function_calls_setjmp = 1;
8609 /* Set TARGET to zero and branch to the first-time-through label. */
8610 emit_move_insn (target, const0_rtx);
8611 emit_jump_insn (gen_jump (first_label));
8612 emit_barrier ();
8613 emit_label (lab1);
8598
8614
8599 /* Set this so all the registers get saved in our frame; we need to be
8600 able to copy the saved values for any registers from frames we unwind. */
8615 /* Tell flow about the strange goings on. Putting `lab1' on
8616 `nonlocal_goto_handler_labels' to indicates that function
8617 calls may traverse the arc back to this label. */
8618
8601 current_function_has_nonlocal_label = 1;
8619 current_function_has_nonlocal_label = 1;
8602}
8620 nonlocal_goto_handler_labels =
8621 gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
8603
8622
8604/* Construct the trailing part of a __builtin_setjmp call.
8605 This is used directly by sjlj exception handling code. */
8606
8607void
8608expand_builtin_setjmp_receiver (receiver_label)
8609 rtx receiver_label ATTRIBUTE_UNUSED;
8610{
8611 /* Clobber the FP when we get here, so we have to make sure it's
8612 marked as used by this function. */
8613 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
8614
8615 /* Mark the static chain as clobbered here so life information
8616 doesn't get messed up for it. */
8617 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
8618

--- 30 unchanged lines hidden (view full) ---

8649 emit_move_insn (virtual_incoming_args_rtx,
8650 copy_to_reg (arg_pointer_save_area));
8651 }
8652 }
8653#endif
8654
8655#ifdef HAVE_builtin_setjmp_receiver
8656 if (HAVE_builtin_setjmp_receiver)
8623 /* Clobber the FP when we get here, so we have to make sure it's
8624 marked as used by this function. */
8625 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
8626
8627 /* Mark the static chain as clobbered here so life information
8628 doesn't get messed up for it. */
8629 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
8630

--- 30 unchanged lines hidden (view full) ---

8661 emit_move_insn (virtual_incoming_args_rtx,
8662 copy_to_reg (arg_pointer_save_area));
8663 }
8664 }
8665#endif
8666
8667#ifdef HAVE_builtin_setjmp_receiver
8668 if (HAVE_builtin_setjmp_receiver)
8657 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
8669 emit_insn (gen_builtin_setjmp_receiver (lab1));
8658 else
8659#endif
8660#ifdef HAVE_nonlocal_goto_receiver
8661 if (HAVE_nonlocal_goto_receiver)
8662 emit_insn (gen_nonlocal_goto_receiver ());
8663 else
8664#endif
8665 {
8666 ; /* Nothing */
8667 }
8668
8670 else
8671#endif
8672#ifdef HAVE_nonlocal_goto_receiver
8673 if (HAVE_nonlocal_goto_receiver)
8674 emit_insn (gen_nonlocal_goto_receiver ());
8675 else
8676#endif
8677 {
8678 ; /* Nothing */
8679 }
8680
8669 /* @@@ This is a kludge. Not all machine descriptions define a blockage
8670 insn, but we must not allow the code we just generated to be reordered
8671 by scheduling. Specifically, the update of the frame pointer must
8672 happen immediately, not later. So emit an ASM_INPUT to act as blockage
8673 insn. */
8674 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
8675}
8676
8677
8678/* __builtin_setjmp is passed a pointer to an array of five words (not
8679 all will be used on all machines). It operates similarly to the C
8680 library function of the same name, but is more efficient. Much of
8681 the code below (and for longjmp) is copied from the handling of
8682 non-local gotos.
8683
8684 NOTE: This is intended for use by GNAT and the exception handling
8685 scheme in the compiler and will only work in the method used by
8686 them. */
8687
8688static rtx
8689expand_builtin_setjmp (arglist, target)
8690 tree arglist;
8691 rtx target;
8692{
8693 rtx buf_addr, next_lab, cont_lab;
8694
8695 if (arglist == 0
8696 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
8697 return NULL_RTX;
8698
8699 if (target == 0 || GET_CODE (target) != REG
8700 || REGNO (target) < FIRST_PSEUDO_REGISTER)
8701 target = gen_reg_rtx (TYPE_MODE (integer_type_node));
8702
8703 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
8704
8705 next_lab = gen_label_rtx ();
8706 cont_lab = gen_label_rtx ();
8707
8708 expand_builtin_setjmp_setup (buf_addr, next_lab);
8709
8710 /* Set TARGET to zero and branch to the continue label. */
8711 emit_move_insn (target, const0_rtx);
8712 emit_jump_insn (gen_jump (cont_lab));
8681 /* Set TARGET, and branch to the next-time-through label. */
8682 emit_move_insn (target, const1_rtx);
8683 emit_jump_insn (gen_jump (next_label));
8713 emit_barrier ();
8684 emit_barrier ();
8714 emit_label (next_lab);
8715
8685
8716 expand_builtin_setjmp_receiver (next_lab);
8717
8718 /* Set TARGET to one. */
8719 emit_move_insn (target, const1_rtx);
8720 emit_label (cont_lab);
8721
8722 /* Tell flow about the strange goings on. Putting `next_lab' on
8723 `nonlocal_goto_handler_labels' to indicates that function
8724 calls may traverse the arc back to this label. */
8725
8726 current_function_has_nonlocal_label = 1;
8727 nonlocal_goto_handler_labels
8728 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
8729
8730 return target;
8731}
8732
8733void
8734expand_builtin_longjmp (buf_addr, value)
8735 rtx buf_addr, value;
8736{
8737 rtx fp, lab, stack;

--- 1004 unchanged lines hidden (view full) ---

9742 }
9743#else
9744 case BUILT_IN_STRCMP:
9745 case BUILT_IN_MEMCMP:
9746 break;
9747#endif
9748
9749 case BUILT_IN_SETJMP:
8686 return target;
8687}
8688
8689void
8690expand_builtin_longjmp (buf_addr, value)
8691 rtx buf_addr, value;
8692{
8693 rtx fp, lab, stack;

--- 1004 unchanged lines hidden (view full) ---

9698 }
9699#else
9700 case BUILT_IN_STRCMP:
9701 case BUILT_IN_MEMCMP:
9702 break;
9703#endif
9704
9705 case BUILT_IN_SETJMP:
9750 target = expand_builtin_setjmp (arglist, target);
9751 if (target)
9752 return target;
9753 break;
9706 if (arglist == 0
9707 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
9708 break;
9709 else
9710 {
9711 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
9712 VOIDmode, 0);
9713 rtx lab = gen_label_rtx ();
9714 rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab);
9715 emit_label (lab);
9716 return ret;
9717 }
9754
9755 /* __builtin_longjmp is passed a pointer to an array of five words.
9756 It's similar to the C library longjmp function but works with
9757 __builtin_setjmp above. */
9758 case BUILT_IN_LONGJMP:
9759 if (arglist == 0 || TREE_CHAIN (arglist) == 0
9760 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
9761 break;

--- 2082 unchanged lines hidden ---
9718
9719 /* __builtin_longjmp is passed a pointer to an array of five words.
9720 It's similar to the C library longjmp function but works with
9721 __builtin_setjmp above. */
9722 case BUILT_IN_LONGJMP:
9723 if (arglist == 0 || TREE_CHAIN (arglist) == 0
9724 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
9725 break;

--- 2082 unchanged lines hidden ---