/* Subroutines for manipulating rtx's in semantically interesting ways.
Copyright (C) 1987, 1991, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
rtx
expr_size (tree exp)
{
- tree size = (*lang_hooks.expr_size) (exp);
-
- if (CONTAINS_PLACEHOLDER_P (size))
- size = build (WITH_RECORD_EXPR, sizetype, size, exp);
+ tree size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
}
HOST_WIDE_INT
int_expr_size (tree exp)
{
- tree t = (*lang_hooks.expr_size) (exp);
+ tree t = lang_hooks.expr_size (exp);
if (t == 0
|| TREE_CODE (t) != INTEGER_CST
return x;
}
-#ifdef POINTERS_EXTEND_UNSIGNED
-
/* Given X, a memory address in ptr_mode, convert it to an address
in Pmode, or vice versa (TO_MODE says which way). We take advantage of
the fact that pointers are not allowed to overflow by commuting arithmetic
used. */
rtx
-convert_memory_address (enum machine_mode to_mode, rtx x)
+convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
+ rtx x)
{
- enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
+#ifndef POINTERS_EXTEND_UNSIGNED
+ return x;
+#else /* defined(POINTERS_EXTEND_UNSIGNED) */
+ enum machine_mode from_mode;
rtx temp;
enum rtx_code code;
+ /* If X already has the right mode, just return it. */
+ if (GET_MODE (x) == to_mode)
+ return x;
+
+ from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
+
/* Here we handle some special cases. If none of them apply, fall through
to the default case. */
switch (GET_CODE (x))
return convert_modes (to_mode, from_mode,
x, POINTERS_EXTEND_UNSIGNED);
+#endif /* defined(POINTERS_EXTEND_UNSIGNED) */
}
-#endif
/* Given a memory address or facsimile X, construct a new address,
currently equivalent, that is stable: future stores won't change it.
if (GET_CODE (x) == ADDRESSOF)
return x;
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (x) != Pmode)
- x = convert_memory_address (Pmode, x);
-#endif
+ x = convert_memory_address (Pmode, x);
- /* By passing constant addresses thru registers
+ /* By passing constant addresses through registers
we get a chance to cse them. */
if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
x = force_reg (Pmode, x);
&& ! rtx_equal_p (x, SET_SRC (set)))
set_unique_reg_note (insn, REG_EQUAL, x);
+ /* Let optimizers know that TEMP is a pointer, and if so, the
+ known alignment of that pointer. */
+ {
+ unsigned align = 0;
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ align = BITS_PER_UNIT;
+ if (SYMBOL_REF_DECL (x) && DECL_P (SYMBOL_REF_DECL (x)))
+ align = DECL_ALIGN (SYMBOL_REF_DECL (x));
+ }
+ else if (GET_CODE (x) == LABEL_REF)
+ align = BITS_PER_UNIT;
+ else if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ {
+ rtx s = XEXP (XEXP (x, 0), 0);
+ rtx c = XEXP (XEXP (x, 0), 1);
+ unsigned sa, ca;
+
+ sa = BITS_PER_UNIT;
+ if (SYMBOL_REF_DECL (s) && DECL_P (SYMBOL_REF_DECL (s)))
+ sa = DECL_ALIGN (SYMBOL_REF_DECL (s));
+
+ ca = exact_log2 (INTVAL (c) & -INTVAL (c)) * BITS_PER_UNIT;
+
+ align = MIN (sa, ca);
+ }
+
+ if (align)
+ mark_reg_pointer (temp, align);
+ }
+
return temp;
}
return x;
temp = gen_reg_rtx (GET_MODE (x));
+
+ if (MEM_POINTER (x))
+ REG_POINTER (temp) = 1;
+
emit_move_insn (temp, x);
return temp;
}
FOR_CALL is nonzero if this call is promoting args for a call. */
+#if defined(PROMOTE_MODE) && !defined(PROMOTE_FUNCTION_MODE)
+#define PROMOTE_FUNCTION_MODE PROMOTE_MODE
+#endif
+
enum machine_mode
promote_mode (tree type, enum machine_mode mode, int *punsignedp,
int for_call ATTRIBUTE_UNUSED)
enum tree_code code = TREE_CODE (type);
int unsignedp = *punsignedp;
-#ifdef PROMOTE_FOR_CALL_ONLY
+#ifndef PROMOTE_MODE
if (! for_call)
return mode;
#endif
switch (code)
{
-#ifdef PROMOTE_MODE
+#ifdef PROMOTE_FUNCTION_MODE
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case CHAR_TYPE: case REAL_TYPE: case OFFSET_TYPE:
- PROMOTE_MODE (mode, unsignedp, type);
+#ifdef PROMOTE_MODE
+ if (for_call)
+ {
+#endif
+ PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+#ifdef PROMOTE_MODE
+ }
+ else
+ {
+ PROMOTE_MODE (mode, unsignedp, type);
+ }
+#endif
break;
#endif
*psave = sa = gen_reg_rtx (mode);
}
}
- else
- {
- if (mode == VOIDmode || GET_MODE (sa) != mode)
- abort ();
- }
if (after)
{
else
emit_insn (fcn (stack_pointer_rtx, sa));
}
+
+/* Invoke emit_stack_save on the nonlocal_goto_save_area for the current
+ function. This function should be called whenever we allocate or
+ deallocate dynamic stack space. */
+
+void
+update_nonlocal_goto_save_area (void)
+{
+ tree t_save;
+ rtx r_save;
+
+ /* The nonlocal_goto_save_area object is an array of N pointers. The
+ first one is used for the frame pointer save; the rest are sized by
+ STACK_SAVEAREA_MODE. Create a reference to array index 1, the first
+ of the stack save area slots. */
+ t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
+ integer_one_node);
+ r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
+
+ emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
+}
\f
#ifdef SETJMP_VIA_SAVE_AREA
/* Optimize RTL generated by allocate_dynamic_stack_space for targets
}
/* Record the new stack level for nonlocal gotos. */
- if (nonlocal_goto_handler_slots != 0)
- emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
+ if (cfun->nonlocal_goto_save_area != 0)
+ update_nonlocal_goto_save_area ();
return target;
}
stack_pointer_rtx,
plus_constant (size, first)));
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (addr) != ptr_mode)
- addr = convert_memory_address (ptr_mode, addr);
-#endif
-
+ addr = convert_memory_address (ptr_mode, addr);
emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
ptr_mode);
}
|| REGNO (test_addr) < FIRST_PSEUDO_REGISTER)
test_addr = force_reg (Pmode, test_addr);
- emit_note (NOTE_INSN_LOOP_BEG);
emit_jump (test_lab);
emit_label (loop_lab);
emit_stack_probe (test_addr);
- emit_note (NOTE_INSN_LOOP_CONT);
-
#ifdef STACK_GROWS_DOWNWARD
#define CMP_OPCODE GTU
temp = expand_binop (Pmode, sub_optab, test_addr, incr, test_addr,
emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
NULL_RTX, Pmode, 1, loop_lab);
emit_jump (end_lab);
- emit_note (NOTE_INSN_LOOP_END);
emit_label (end_lab);
emit_stack_probe (last_addr);