/* Definitions for code generation pass of GNU compiler.
Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
#define QUEUED_NEXT(P) XEXP (P, 4)
/* This is the 4th arg to `expand_expr'.
+ EXPAND_STACK_PARM means we are possibly expanding a call param onto
+ the stack. Choosing a value of 2 isn't special; It just allows
+ some code optimization in store_expr.
EXPAND_SUM means it is ok to return a PLUS rtx or MULT rtx.
EXPAND_INITIALIZER is similar but also record any labels on forced_labels.
EXPAND_CONST_ADDRESS means it is ok to return a MEM whose address
is a constant that is not a legitimate address.
- EXPAND_MEMORY_USE_* are explained below. */
-enum expand_modifier {EXPAND_NORMAL, EXPAND_SUM,
- EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER,
- EXPAND_MEMORY_USE_WO, EXPAND_MEMORY_USE_RW,
- EXPAND_MEMORY_USE_BAD, EXPAND_MEMORY_USE_DONT};
-
-/* Argument for chkr_* functions.
- MEMORY_USE_RO: the pointer reads memory.
- MEMORY_USE_WO: the pointer writes to memory.
- MEMORY_USE_RW: the pointer modifies memory (ie it reads and writes). An
- example is (*ptr)++
- MEMORY_USE_BAD: use this if you don't know the behavior of the pointer, or
- if you know there are no pointers. Using an INDIRECT_REF
- with MEMORY_USE_BAD will abort.
- MEMORY_USE_TW: just test for writing, without update. Special.
- MEMORY_USE_DONT: the memory is neither read nor written. This is used by
- '->' and '.'. */
-enum memory_use_mode {MEMORY_USE_BAD = 0, MEMORY_USE_RO = 1,
- MEMORY_USE_WO = 2, MEMORY_USE_RW = 3,
- MEMORY_USE_TW = 6, MEMORY_USE_DONT = 99};
+ EXPAND_WRITE means we are only going to write to the resulting rtx.
+ EXPAND_MEMORY means we are interested in a memory result, even if
+ the memory is constant and we could have propagated a constant value. */
+enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM = 2, EXPAND_SUM,
+ EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
+ EXPAND_MEMORY};
/* Prevent the compiler from deferring stack pops. See
inhibit_defer_pop for more information. */
more information. */
#define OK_DEFER_POP (inhibit_defer_pop -= 1)
\f
+enum direction {none, upward, downward};
+
#ifdef TREE_CODE /* Don't lose if tree.h not included. */
/* Structure to record the size of a sequence of arguments
as the sum of a tree-expression and a constant. This structure is
HOST_WIDE_INT constant;
tree var;
};
+
+/* Package up various arg related fields of struct args for
+ locate_and_pad_parm. */
+struct locate_and_pad_arg_data
+{
+ /* Size of this argument on the stack, rounded up for any padding it
+ gets. If REG_PARM_STACK_SPACE is defined, then register parms are
+ counted here, otherwise they aren't. */
+ struct args_size size;
+ /* Offset of this argument from beginning of stack-args. */
+ struct args_size offset;
+ /* Offset to the start of the stack slot. Different from OFFSET
+ if this arg pads downward. */
+ struct args_size slot_offset;
+ /* The amount that the stack pointer needs to be adjusted to
+ force alignment for the next argument. */
+ struct args_size alignment_pad;
+};
#endif
/* Add the value of the tree INC to the `struct args_size' TO. */
-#define ADD_PARM_SIZE(TO, INC) \
-{ tree inc = (INC); \
- if (host_integerp (inc, 0)) \
- (TO).constant += tree_low_cst (inc, 0); \
- else if ((TO).var == 0) \
- (TO).var = inc; \
- else \
- (TO).var = size_binop (PLUS_EXPR, (TO).var, inc); }
-
-#define SUB_PARM_SIZE(TO, DEC) \
-{ tree dec = (DEC); \
- if (host_integerp (dec, 0)) \
- (TO).constant -= tree_low_cst (dec, 0); \
- else if ((TO).var == 0) \
- (TO).var = size_binop (MINUS_EXPR, ssize_int (0), dec); \
- else \
- (TO).var = size_binop (MINUS_EXPR, (TO).var, dec); }
+#define ADD_PARM_SIZE(TO, INC) \
+do { \
+ tree inc = (INC); \
+ if (host_integerp (inc, 0)) \
+ (TO).constant += tree_low_cst (inc, 0); \
+ else if ((TO).var == 0) \
+ (TO).var = convert (ssizetype, inc); \
+ else \
+ (TO).var = size_binop (PLUS_EXPR, (TO).var, \
+ convert (ssizetype, inc)); \
+} while (0)
+
+#define SUB_PARM_SIZE(TO, DEC) \
+do { \
+ tree dec = (DEC); \
+ if (host_integerp (dec, 0)) \
+ (TO).constant -= tree_low_cst (dec, 0); \
+ else if ((TO).var == 0) \
+ (TO).var = size_binop (MINUS_EXPR, ssize_int (0), \
+ convert (ssizetype, dec)); \
+ else \
+ (TO).var = size_binop (MINUS_EXPR, (TO).var, \
+ convert (ssizetype, dec)); \
+} while (0)
/* Convert the implicit sum in a `struct args_size' into a tree
of type ssizetype. */
#define ARGS_SIZE_TREE(SIZE) \
((SIZE).var == 0 ? ssize_int ((SIZE).constant) \
- : size_binop (PLUS_EXPR, (SIZE).var, ssize_int ((SIZE).constant)))
+ : size_binop (PLUS_EXPR, convert (ssizetype, (SIZE).var), \
+ ssize_int ((SIZE).constant)))
/* Convert the implicit sum in a `struct args_size' into an rtx. */
#define ARGS_SIZE_RTX(SIZE) \
((SIZE).var == 0 ? GEN_INT ((SIZE).constant) \
- : expand_expr (ARGS_SIZE_TREE (SIZE), NULL_RTX, VOIDmode, \
- EXPAND_MEMORY_USE_BAD))
+ : expand_expr (ARGS_SIZE_TREE (SIZE), NULL_RTX, VOIDmode, 0))
/* Supply a default definition for FUNCTION_ARG_PADDING:
usually pad upward, but pad short args downward on
big-endian machines. */
-enum direction {none, upward, downward}; /* Value has this type. */
-
#ifndef FUNCTION_ARG_PADDING
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
(! BYTES_BIG_ENDIAN \
/* Supply a default definition for FUNCTION_ARG_BOUNDARY. Normally, we let
FUNCTION_ARG_PADDING, which also pads the length, handle any needed
alignment. */
-
+
#ifndef FUNCTION_ARG_BOUNDARY
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) PARM_BOUNDARY
#endif
+/* Define to nonzero if complex arguments should be split into their
+ corresponding components. */
+#ifndef SPLIT_COMPLEX_ARGS
+#define SPLIT_COMPLEX_ARGS 0
+#endif
+tree split_complex_types (tree);
+tree split_complex_values (tree);
+
/* Provide a default value for STRICT_ARGUMENT_NAMING. */
#ifndef STRICT_ARGUMENT_NAMING
#define STRICT_ARGUMENT_NAMING 0
#define PRETEND_OUTGOING_VARARGS_NAMED 0
#endif
-/* Nonzero if we do not know how to pass TYPE solely in registers.
- We cannot do so in the following cases:
-
- - if the type has variable size
- - if the type is marked as addressable (it is required to be constructed
- into the stack)
- - if the padding and mode of the type is such that a copy into a register
- would put it into the wrong part of the register.
-
- Which padding can't be supported depends on the byte endianness.
-
- A value in a register is implicitly padded at the most significant end.
- On a big-endian machine, that is the lower end in memory.
- So a value padded in memory at the upper end can't go in a register.
- For a little-endian machine, the reverse is true. */
-
+/* Nonzero if we do not know how to pass TYPE solely in registers. */
+extern bool default_must_pass_in_stack PARAMS((enum machine_mode, tree));
#ifndef MUST_PASS_IN_STACK
-#define MUST_PASS_IN_STACK(MODE,TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE) \
- || ((MODE) == BLKmode \
- && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
- && 0 == (int_size_in_bytes (TYPE) \
- % (PARM_BOUNDARY / BITS_PER_UNIT))) \
- && (FUNCTION_ARG_PADDING (MODE, TYPE) \
- == (BYTES_BIG_ENDIAN ? upward : downward)))))
+#define MUST_PASS_IN_STACK(MODE,TYPE) default_must_pass_in_stack(MODE, TYPE)
#endif
/* Nonzero if type TYPE should be returned in memory.
extern int have_add2_insn PARAMS ((rtx, rtx));
extern int have_sub2_insn PARAMS ((rtx, rtx));
-/* Emit a pair of rtl insns to compare two rtx's and to jump
+/* Emit a pair of rtl insns to compare two rtx's and to jump
to a label if the comparison is true. */
extern void emit_cmp_and_jump_insns PARAMS ((rtx, rtx, enum rtx_code, rtx,
- enum machine_mode, int,
- unsigned int, rtx));
+ enum machine_mode, int, rtx));
/* Generate code to indirectly jump to a location given in the rtx LOC. */
extern void emit_indirect_jump PARAMS ((rtx));
enum machine_mode, rtx, rtx,
enum machine_mode, int));
-/* Return non-zero if the conditional move is supported. */
+/* Return nonzero if the conditional move is supported. */
int can_conditionally_move_p PARAMS ((enum machine_mode mode));
#endif
+rtx emit_conditional_add PARAMS ((rtx, enum rtx_code, rtx, rtx,
+ enum machine_mode, rtx, rtx,
+ enum machine_mode, int));
\f
/* Functions from expmed.c: */
extern rtx negate_rtx PARAMS ((enum machine_mode, rtx));
/* Expand a logical AND operation. */
-extern rtx expand_and PARAMS ((rtx, rtx, rtx));
+extern rtx expand_and PARAMS ((enum machine_mode, rtx, rtx, rtx));
/* Emit a store-flag operation. */
extern rtx emit_store_flag PARAMS ((rtx, enum rtx_code, rtx, rtx,
extern rtx gen_cond_trap PARAMS ((enum rtx_code, rtx, rtx, rtx));
\f
/* Functions from builtins.c: */
-#ifdef TREE_CODE
extern rtx expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
-extern void std_expand_builtin_va_start PARAMS ((int, tree, rtx));
+extern void std_expand_builtin_va_start PARAMS ((tree, rtx));
extern rtx std_expand_builtin_va_arg PARAMS ((tree, tree));
extern rtx expand_builtin_va_arg PARAMS ((tree, tree));
extern void default_init_builtins PARAMS ((void));
extern rtx default_expand_builtin PARAMS ((tree, rtx, rtx,
enum machine_mode, int));
-#endif
-
extern void expand_builtin_setjmp_setup PARAMS ((rtx, rtx));
extern void expand_builtin_setjmp_receiver PARAMS ((rtx));
extern void expand_builtin_longjmp PARAMS ((rtx, rtx));
extern rtx expand_builtin_saveregs PARAMS ((void));
+extern void expand_builtin_trap PARAMS ((void));
extern HOST_WIDE_INT get_varargs_alias_set PARAMS ((void));
extern HOST_WIDE_INT get_frame_alias_set PARAMS ((void));
extern void record_base_value PARAMS ((unsigned int, rtx, int));
/* This is run at the start of compiling a function. */
extern void init_expr PARAMS ((void));
-/* This function is run once to initialize stor-layout.c. */
-
-extern void init_stor_layout_once PARAMS ((void));
-
/* This is run at the end of compiling a function. */
extern void finish_expr_for_function PARAMS ((void));
rtx, int));
/* Emit code to move a block Y to a block X. */
-extern rtx emit_block_move PARAMS ((rtx, rtx, rtx));
+
+enum block_op_methods
+{
+ BLOCK_OP_NORMAL,
+ BLOCK_OP_NO_LIBCALL,
+ BLOCK_OP_CALL_PARM
+};
+
+extern void init_block_move_fn PARAMS ((const char *));
+extern void init_block_clear_fn PARAMS ((const char *));
+
+extern rtx emit_block_move PARAMS ((rtx, rtx, rtx, enum block_op_methods));
/* Copy all or part of a value X into registers starting at REGNO.
The number of registers to be filled is NREGS. */
/* Copy all or part of a BLKmode value X out of registers starting at REGNO.
The number of registers to be filled is NREGS. */
-extern void move_block_from_reg PARAMS ((int, rtx, int, int));
+extern void move_block_from_reg PARAMS ((int, rtx, int));
+
+/* Generate a non-consecutive group of registers represented by a PARALLEL. */
+extern rtx gen_group_rtx PARAMS ((rtx));
/* Load a BLKmode value into non-consecutive registers represented by a
PARALLEL. */
-extern void emit_group_load PARAMS ((rtx, rtx, int, unsigned int));
+extern void emit_group_load PARAMS ((rtx, rtx, int));
+
+/* Move a non-consecutive group of registers represented by a PARALLEL into
+ a non-consecutive group of registers represented by a PARALLEL. */
+extern void emit_group_move PARAMS ((rtx, rtx));
/* Store a BLKmode value from non-consecutive registers represented by a
PARALLEL. */
-extern void emit_group_store PARAMS ((rtx, rtx, int, unsigned int));
+extern void emit_group_store PARAMS ((rtx, rtx, int));
#ifdef TREE_CODE
/* Copy BLKmode object from a set of registers. */
-extern rtx copy_blkmode_from_reg PARAMS ((rtx,rtx,tree));
+extern rtx copy_blkmode_from_reg PARAMS ((rtx, rtx, tree));
#endif
/* Mark REG as holding a parameter for the next CALL_INSN. */
If OBJECT has BLKmode, SIZE is its length in bytes. */
extern rtx clear_storage PARAMS ((rtx, rtx));
-/* Return non-zero if it is desirable to store LEN bytes generated by
+/* Determine whether the LEN bytes can be moved by using several move
+ instructions. Return nonzero if a call to move_by_pieces should
+ succeed. */
+extern int can_move_by_pieces PARAMS ((unsigned HOST_WIDE_INT, unsigned int));
+
+/* Return nonzero if it is desirable to store LEN bytes generated by
CONSTFUN with several move instructions by store_by_pieces
function. CONSTFUNDATA is a pointer which will be passed as argument
in every CONSTFUN call.
/* Generate several move instructions to store LEN bytes generated by
CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a
pointer which will be passed as argument in every CONSTFUN call.
- ALIGN is maximum alignment we can assume. */
-extern void store_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
- rtx (*) (PTR, HOST_WIDE_INT,
- enum machine_mode),
- PTR, unsigned int));
+ ALIGN is maximum alignment we can assume.
+ Returns TO + LEN. */
+extern rtx store_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
+ rtx (*) (PTR, HOST_WIDE_INT,
+ enum machine_mode),
+ PTR, unsigned int, int));
/* Emit insns to set X from Y. */
extern rtx emit_move_insn PARAMS ((rtx, rtx));
/* Generate rtl to compare two rtx's, will call emit_cmp_insn. */
extern rtx compare_from_rtx PARAMS ((rtx, rtx, enum rtx_code, int,
- enum machine_mode, rtx, unsigned int));
+ enum machine_mode, rtx));
extern void do_compare_rtx_and_jump PARAMS ((rtx, rtx, enum rtx_code, int,
enum machine_mode, rtx,
- unsigned int, rtx, rtx));
+ rtx, rtx));
/* Two different ways of generating switch statements. */
extern int try_casesi PARAMS ((tree, tree, tree, tree, rtx, rtx));
/* Return an rtx for the size in bytes of the value of an expr. */
extern rtx expr_size PARAMS ((tree));
+/* Return a wide integer for the size in bytes of the value of EXP, or -1
+ if the size can vary or is larger than an integer. */
+extern HOST_WIDE_INT int_expr_size PARAMS ((tree));
+
extern rtx lookup_static_chain PARAMS ((tree));
/* Convert a stack slot address ADDR valid in function FNDECL
rtx, int));
extern rtx expand_divmod PARAMS ((int, enum tree_code, enum machine_mode, rtx,
rtx, rtx, int));
-extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, tree,
- struct args_size *,
- struct args_size *,
- struct args_size *,
- struct args_size *));
+extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, int,
+ tree, struct args_size *,
+ struct locate_and_pad_arg_data *));
extern rtx expand_inline_function PARAMS ((tree, tree, rtx, int, tree, rtx));
/* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary. */
extern rtx label_rtx PARAMS ((tree));
+
+/* As label_rtx, but additionally the label is placed on the forced label
+ list of its containing function (i.e. it is treated as reachable even
+ if how is not obvious). */
+extern rtx force_label_rtx PARAMS ((tree));
#endif
/* Indicate how an input argument register was promoted. */
/* Set the alignment of MEM to ALIGN bits. */
extern void set_mem_align PARAMS ((rtx, unsigned int));
-/* Set the DECL for MEM to DECL. */
-extern void set_mem_decl PARAMS ((rtx, tree));
+/* Set the expr for MEM to EXPR. */
+extern void set_mem_expr PARAMS ((rtx, tree));
+
+/* Set the offset for MEM to OFFSET. */
+extern void set_mem_offset PARAMS ((rtx, rtx));
+
+/* Set the size for MEM to SIZE. */
+extern void set_mem_size PARAMS ((rtx, rtx));
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address changed to ADDR.
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address offset by OFFSET bytes. */
#define adjust_address(MEMREF, MODE, OFFSET) \
- adjust_address_1 (MEMREF, MODE, OFFSET, 1)
+ adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1)
/* Likewise, but the reference is not required to be valid. */
#define adjust_address_nv(MEMREF, MODE, OFFSET) \
- adjust_address_1 (MEMREF, MODE, OFFSET, 0)
+ adjust_address_1 (MEMREF, MODE, OFFSET, 0, 1)
+
+/* Return a memory reference like MEMREF, but with its mode changed
+ to MODE and its address changed to ADDR, which is assumed to be
+ increased by OFFSET bytes from MEMREF. */
+#define adjust_automodify_address(MEMREF, MODE, ADDR, OFFSET) \
+ adjust_automodify_address_1 (MEMREF, MODE, ADDR, OFFSET, 1)
+
+/* Likewise, but the reference is not required to be valid. */
+#define adjust_automodify_address_nv(MEMREF, MODE, ADDR, OFFSET) \
+ adjust_automodify_address_1 (MEMREF, MODE, ADDR, OFFSET, 0)
extern rtx adjust_address_1 PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT,
- int));
+ int, int));
+extern rtx adjust_automodify_address_1 PARAMS ((rtx, enum machine_mode,
+ rtx, HOST_WIDE_INT, int));
/* Return a memory reference like MEMREF, but whose address is changed by
adding OFFSET, an RTX, to it. POW2 is the highest power of two factor
known to be in OFFSET (possibly 1). */
-extern rtx offset_address PARAMS ((rtx, rtx, HOST_WIDE_INT));
+extern rtx offset_address PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT));
/* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed
/* Likewise, but the reference is not required to be valid. */
extern rtx replace_equiv_address_nv PARAMS ((rtx, rtx));
+/* Return a memory reference like MEMREF, but with its mode widened to
+ MODE and adjusted by OFFSET. */
+extern rtx widen_memory_access PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT));
+
/* Return a memory reference like MEMREF, but which is known to have a
valid address. */
extern rtx validize_mem PARAMS ((rtx));
corresponding to REF, set the memory attributes. OBJECTP is nonzero
if we are making a new object of this type. */
extern void set_mem_attributes PARAMS ((rtx, tree, int));
+
+/* Similar, except that BITPOS has not yet been applied to REF, so if
+ we alter MEM_OFFSET according to T then we should subtract BITPOS
+ expecting that it'll be added back in later. */
+extern void set_mem_attributes_minus_bitpos PARAMS ((rtx, tree, int,
+ HOST_WIDE_INT));
#endif
/* Assemble the static constant template for function entry trampolines. */
says how many bytes. */
extern rtx allocate_dynamic_stack_space PARAMS ((rtx, rtx, int));
-/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
+/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
FIRST is a constant and size is a Pmode RTX. These are offsets from the
current stack pointer. STACK_GROWS_DOWNWARD says whether to add or
subtract from the stack. If SIZE is constant, this is done
extern rtx store_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
- enum machine_mode, rtx,
- unsigned int, HOST_WIDE_INT));
+ enum machine_mode, rtx, HOST_WIDE_INT));
extern rtx extract_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, int, rtx,
enum machine_mode, enum machine_mode,
- unsigned int, HOST_WIDE_INT));
+ HOST_WIDE_INT));
extern rtx expand_mult PARAMS ((enum machine_mode, rtx, rtx, rtx, int));
+extern bool const_mult_add_overflow_p PARAMS ((rtx, rtx, rtx, enum machine_mode, int));
extern rtx expand_mult_add PARAMS ((rtx, rtx, rtx, rtx,enum machine_mode, int));
extern rtx expand_mult_highpart_adjust PARAMS ((enum machine_mode, rtx, rtx, rtx, rtx, int));
-extern rtx assemble_static_space PARAMS ((int));
-
-/* Hook called by expand_expr for language-specific tree codes.
- It is up to the language front end to install a hook
- if it has any such codes that expand_expr needs to know about. */
-extern rtx (*lang_expand_expr) PARAMS ((union tree_node *, rtx,
- enum machine_mode,
- enum expand_modifier modifier));
-
-#ifdef TREE_CODE
-/* Hook called by output_constant for language-specific tree codes.
- It is up to the language front-end to install a hook if it has any
- such codes that output_constant needs to know about. Returns a
- language-independent constant equivalent to its input. */
-extern tree (*lang_expand_constant) PARAMS ((tree));
-
+extern rtx assemble_static_space PARAMS ((unsigned HOST_WIDE_INT));
extern int safe_from_p PARAMS ((rtx, tree, int));
-/* Hook called by safe_from_p for language-specific tree codes. It is
- up to the language front-end to install a hook if it has any such
- codes that safe_from_p needs to know about. Since same_from_p will
- recursively explore the TREE_OPERANDs of an expression, this hook
- should not reexamine those pieces. This routine may recursively
- call safe_from_p; it should always pass `0' as the TOP_P
- parameter. */
-extern int (*lang_safe_from_p) PARAMS ((rtx, tree));
-#endif
-
/* Call this once to initialize the contents of the optabs
appropriately for the current target machine. */
extern void init_optabs PARAMS ((void));
extern void mark_seen_cases PARAMS ((tree, unsigned char *,
HOST_WIDE_INT, int));
#endif
+
+extern int vector_mode_valid_p PARAMS ((enum machine_mode));
+
+extern tree placeholder_list;