Commit 921b3427 by Richard Kenner

(expand_builtin, case BUILT_IN_AGGREGATE_INCOMING_ADDRESS): New case.

(expand_assignment, expand_expr, emit_push_insn, store_expr):
Insert calls to chkr_check_addr, chkr_set_right, and chkr_copy_bitmap
when -fcheck-memory-usage.
(get_push_address, get_memory_usage_from_modifier): New functions.

From-SVN: r14611
parent 8fbea4dc
...@@ -147,6 +147,7 @@ struct clear_by_pieces ...@@ -147,6 +147,7 @@ struct clear_by_pieces
as well as depth of arithmetic stack. (Notice that variables are as well as depth of arithmetic stack. (Notice that variables are
stored on the machine's stack, not the arithmetic stack.) */ stored on the machine's stack, not the arithmetic stack.) */
static rtx get_push_address PROTO ((int));
extern int local_vars_size; extern int local_vars_size;
extern int stack_depth; extern int stack_depth;
extern int max_stack_depth; extern int max_stack_depth;
...@@ -2368,6 +2369,25 @@ gen_push_operand () ...@@ -2368,6 +2369,25 @@ gen_push_operand ()
return gen_rtx (STACK_PUSH_CODE, Pmode, stack_pointer_rtx); return gen_rtx (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
} }
/* Return an rtx for the address of the beginning of a as-if-it-was-pushed
block of SIZE bytes. */
static rtx
get_push_address (size)
int size;
{
register rtx temp;
if (STACK_PUSH_CODE == POST_DEC)
temp = gen_rtx (PLUS, Pmode, stack_pointer_rtx, GEN_INT (size));
else if (STACK_PUSH_CODE == POST_INC)
temp = gen_rtx (MINUS, Pmode, stack_pointer_rtx, GEN_INT (size));
else
temp = stack_pointer_rtx;
return force_operand (temp, NULL_RTX);
}
/* Generate code to push X onto the stack, assuming it has mode MODE and /* Generate code to push X onto the stack, assuming it has mode MODE and
type TYPE. type TYPE.
MODE is redundant except when X is a CONST_INT (since they don't MODE is redundant except when X is a CONST_INT (since they don't
...@@ -2487,6 +2507,25 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, ...@@ -2487,6 +2507,25 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner, move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner,
INTVAL (size) - used, align); INTVAL (size) - used, align);
if (flag_check_memory_usage)
{
rtx temp;
temp = get_push_address (INTVAL(size) - used);
if (GET_CODE (x) == MEM && AGGREGATE_TYPE_P (type))
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
temp, ptr_mode,
XEXP (xinner, 0), ptr_mode,
GEN_INT (INTVAL(size) - used),
TYPE_MODE (sizetype));
else
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
temp, ptr_mode,
GEN_INT (INTVAL(size) - used),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW), QImode);
}
} }
else else
#endif /* PUSH_ROUNDING */ #endif /* PUSH_ROUNDING */
...@@ -2522,6 +2561,22 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, ...@@ -2522,6 +2561,22 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
plus_constant (gen_rtx (PLUS, Pmode, plus_constant (gen_rtx (PLUS, Pmode,
args_addr, args_so_far), args_addr, args_so_far),
skip)); skip));
if (flag_check_memory_usage)
{
rtx target;
target = copy_to_reg (temp);
if (GET_CODE (x) == MEM && AGGREGATE_TYPE_P (type))
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
target, ptr_mode,
XEXP (xinner, 0), ptr_mode,
size, TYPE_MODE (sizetype));
else
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
target, ptr_mode,
size, TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW), QImode);
}
/* TEMP is the address of the block. Copy the data there. */ /* TEMP is the address of the block. Copy the data there. */
if (GET_CODE (size) == CONST_INT if (GET_CODE (size) == CONST_INT
...@@ -2687,6 +2742,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, ...@@ -2687,6 +2742,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
else else
{ {
rtx addr; rtx addr;
rtx target = NULL_RTX;
/* Push padding now if padding above and stack grows down, /* Push padding now if padding above and stack grows down,
or if padding below and stack grows up. or if padding below and stack grows up.
...@@ -2700,15 +2756,38 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, ...@@ -2700,15 +2756,38 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
addr = gen_push_operand (); addr = gen_push_operand ();
else else
#endif #endif
{
if (GET_CODE (args_so_far) == CONST_INT) if (GET_CODE (args_so_far) == CONST_INT)
addr addr
= memory_address (mode, = memory_address (mode,
plus_constant (args_addr, INTVAL (args_so_far))); plus_constant (args_addr,
INTVAL (args_so_far)));
else else
addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr, addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr,
args_so_far)); args_so_far));
target = addr;
}
emit_move_insn (gen_rtx (MEM, mode, addr), x); emit_move_insn (gen_rtx (MEM, mode, addr), x);
if (flag_check_memory_usage)
{
if (target == 0)
target = get_push_address (GET_MODE_SIZE (mode));
if (GET_CODE (x) == MEM && AGGREGATE_TYPE_P (type))
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
target, ptr_mode,
XEXP (x, 0), ptr_mode,
GEN_INT (GET_MODE_SIZE (mode)),
TYPE_MODE (sizetype));
else
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
target, ptr_mode,
GEN_INT (GET_MODE_SIZE (mode)),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW), QImode);
}
} }
ret: ret:
...@@ -2801,7 +2880,7 @@ expand_assignment (to, from, want_value, suggest_reg) ...@@ -2801,7 +2880,7 @@ expand_assignment (to, from, want_value, suggest_reg)
if (mode1 == VOIDmode && want_value) if (mode1 == VOIDmode && want_value)
tem = stabilize_reference (tem); tem = stabilize_reference (tem);
to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0); to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_DONT);
if (offset != 0) if (offset != 0)
{ {
rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
...@@ -2832,6 +2911,31 @@ expand_assignment (to, from, want_value, suggest_reg) ...@@ -2832,6 +2911,31 @@ expand_assignment (to, from, want_value, suggest_reg)
#endif #endif
} }
/* Check the access. */
if (flag_check_memory_usage && GET_CODE (to_rtx) == MEM)
{
rtx to_addr;
int size;
int best_mode_size;
enum machine_mode best_mode;
best_mode = get_best_mode (bitsize, bitpos,
TYPE_ALIGN (TREE_TYPE (tem)),
mode1, volatilep);
if (best_mode == VOIDmode)
best_mode = QImode;
best_mode_size = GET_MODE_BITSIZE (best_mode);
to_addr = plus_constant (XEXP (to_rtx, 0), (bitpos / BITS_PER_UNIT));
size = CEIL ((bitpos % best_mode_size) + bitsize, best_mode_size);
size *= GET_MODE_SIZE (best_mode);
/* Check the access right of the pointer. */
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3, to_addr,
ptr_mode, GEN_INT (size), TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO), QImode);
}
result = store_field (to_rtx, bitsize, bitpos, mode1, from, result = store_field (to_rtx, bitsize, bitpos, mode1, from,
(want_value (want_value
/* Spurious cast makes HPUX compiler happy. */ /* Spurious cast makes HPUX compiler happy. */
...@@ -2873,7 +2977,7 @@ expand_assignment (to, from, want_value, suggest_reg) ...@@ -2873,7 +2977,7 @@ expand_assignment (to, from, want_value, suggest_reg)
push_temp_slots (); push_temp_slots ();
value = expand_expr (from, NULL_RTX, VOIDmode, 0); value = expand_expr (from, NULL_RTX, VOIDmode, 0);
if (to_rtx == 0) if (to_rtx == 0)
to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0); to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO);
/* Handle calls that return values in multiple non-contiguous locations. /* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */ The Irix 6 ABI has examples of this. */
...@@ -2894,7 +2998,7 @@ expand_assignment (to, from, want_value, suggest_reg) ...@@ -2894,7 +2998,7 @@ expand_assignment (to, from, want_value, suggest_reg)
Don't re-expand if it was expanded already (in COMPONENT_REF case). */ Don't re-expand if it was expanded already (in COMPONENT_REF case). */
if (to_rtx == 0) if (to_rtx == 0)
to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0); to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO);
/* Don't move directly into a return register. */ /* Don't move directly into a return register. */
if (TREE_CODE (to) == RESULT_DECL && GET_CODE (to_rtx) == REG) if (TREE_CODE (to) == RESULT_DECL && GET_CODE (to_rtx) == REG)
...@@ -2921,7 +3025,17 @@ expand_assignment (to, from, want_value, suggest_reg) ...@@ -2921,7 +3025,17 @@ expand_assignment (to, from, want_value, suggest_reg)
push_temp_slots (); push_temp_slots ();
size = expr_size (from); size = expr_size (from);
from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0); from_rtx = expand_expr (from, NULL_RTX, VOIDmode,
EXPAND_MEMORY_USE_DONT);
/* Copy the rights of the bitmap. */
if (flag_check_memory_usage)
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
XEXP (to_rtx, 0), ptr_mode,
XEXP (from_rtx, 0), ptr_mode,
convert_to_mode (TYPE_MODE (sizetype),
size, TREE_UNSIGNED (sizetype)),
TYPE_MODE (sizetype));
#ifdef TARGET_MEM_FUNCTIONS #ifdef TARGET_MEM_FUNCTIONS
emit_library_call (memcpy_libfunc, 0, emit_library_call (memcpy_libfunc, 0,
...@@ -3137,6 +3251,22 @@ store_expr (exp, target, want_value) ...@@ -3137,6 +3251,22 @@ store_expr (exp, target, want_value)
temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)), temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
temp, TREE_UNSIGNED (TREE_TYPE (exp))); temp, TREE_UNSIGNED (TREE_TYPE (exp)));
if (flag_check_memory_usage
&& GET_CODE (target) == MEM
&& AGGREGATE_TYPE_P (TREE_TYPE (exp)))
{
if (GET_CODE (temp) == MEM)
emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
XEXP (target, 0), ptr_mode,
XEXP (temp, 0), ptr_mode,
expr_size (exp), TYPE_MODE (sizetype));
else
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
XEXP (target, 0), ptr_mode,
expr_size (exp), TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO), QImode);
}
/* If value was not generated in the target, store it there. /* If value was not generated in the target, store it there.
Convert the value to TARGET's type first if nec. */ Convert the value to TARGET's type first if nec. */
...@@ -3220,6 +3350,12 @@ store_expr (exp, target, want_value) ...@@ -3220,6 +3350,12 @@ store_expr (exp, target, want_value)
if (size != const0_rtx) if (size != const0_rtx)
{ {
/* Be sure we can write on ADDR. */
if (flag_check_memory_usage)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
addr, ptr_mode,
size, TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_WO), QImode);
#ifdef TARGET_MEM_FUNCTIONS #ifdef TARGET_MEM_FUNCTIONS
emit_library_call (memset_libfunc, 0, VOIDmode, 3, emit_library_call (memset_libfunc, 0, VOIDmode, 3,
addr, ptr_mode, addr, ptr_mode,
...@@ -4261,6 +4397,33 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, ...@@ -4261,6 +4397,33 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
return exp; return exp;
} }
/* Subroutine of expand_exp: compute memory_usage from modifier. */
static enum memory_use_mode
get_memory_usage_from_modifier (modifier)
enum expand_modifier modifier;
{
switch (modifier)
{
case EXPAND_NORMAL:
return MEMORY_USE_RO;
break;
case EXPAND_MEMORY_USE_WO:
return MEMORY_USE_WO;
break;
case EXPAND_MEMORY_USE_RW:
return MEMORY_USE_RW;
break;
case EXPAND_INITIALIZER:
case EXPAND_MEMORY_USE_DONT:
case EXPAND_SUM:
case EXPAND_CONST_ADDRESS:
return MEMORY_USE_DONT;
case EXPAND_MEMORY_USE_BAD:
default:
abort ();
}
}
/* Given an rtx VALUE that may contain additions and multiplications, /* Given an rtx VALUE that may contain additions and multiplications,
return an equivalent value that just refers to a register or memory. return an equivalent value that just refers to a register or memory.
This is done by generating instructions to perform the arithmetic This is done by generating instructions to perform the arithmetic
...@@ -4656,7 +4819,15 @@ expand_expr (exp, target, tmode, modifier) ...@@ -4656,7 +4819,15 @@ expand_expr (exp, target, tmode, modifier)
|| code == COND_EXPR) || code == COND_EXPR)
&& TREE_CODE (type) == VOID_TYPE)); && TREE_CODE (type) == VOID_TYPE));
tree context; tree context;
/* Used by check-memory-usage to make modifier read only. */
enum expand_modifier ro_modifier;
/* Make a read-only version of the modifier. */
if (modifier == EXPAND_NORMAL || modifier == EXPAND_SUM
|| modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER)
ro_modifier = modifier;
else
ro_modifier = EXPAND_NORMAL;
if (output_bytecode && modifier != EXPAND_INITIALIZER) if (output_bytecode && modifier != EXPAND_INITIALIZER)
{ {
...@@ -4689,7 +4860,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -4689,7 +4860,7 @@ expand_expr (exp, target, tmode, modifier)
&& TREE_CODE (exp) != FUNCTION_DECL && TREE_CODE (exp) != FUNCTION_DECL
&& mode != VOIDmode && mode != BLKmode) && mode != VOIDmode && mode != BLKmode)
{ {
temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier); temp = expand_expr (exp, NULL_RTX, VOIDmode, ro_modifier);
if (GET_CODE (temp) == MEM) if (GET_CODE (temp) == MEM)
temp = copy_to_reg (temp); temp = copy_to_reg (temp);
return const0_rtx; return const0_rtx;
...@@ -4697,12 +4868,12 @@ expand_expr (exp, target, tmode, modifier) ...@@ -4697,12 +4868,12 @@ expand_expr (exp, target, tmode, modifier)
if (TREE_CODE_CLASS (code) == '1') if (TREE_CODE_CLASS (code) == '1')
return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
VOIDmode, modifier); VOIDmode, ro_modifier);
else if (TREE_CODE_CLASS (code) == '2' else if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<') || TREE_CODE_CLASS (code) == '<')
{ {
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier); expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, ro_modifier);
expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier); expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, ro_modifier);
return const0_rtx; return const0_rtx;
} }
else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
...@@ -4710,7 +4881,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -4710,7 +4881,7 @@ expand_expr (exp, target, tmode, modifier)
/* If the second operand has no side effects, just evaluate /* If the second operand has no side effects, just evaluate
the first. */ the first. */
return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
VOIDmode, modifier); VOIDmode, ro_modifier);
target = 0; target = 0;
} }
...@@ -4776,6 +4947,26 @@ expand_expr (exp, target, tmode, modifier) ...@@ -4776,6 +4947,26 @@ expand_expr (exp, target, tmode, modifier)
pop_obstacks (); pop_obstacks ();
} }
/* Only check automatic variables. Currently, function arguments are
not checked (this can be done at compile-time with prototypes).
Aggregates are not checked. */
if (flag_check_memory_usage && code == VAR_DECL
&& GET_CODE (DECL_RTL (exp)) == MEM
&& DECL_CONTEXT (exp) != NULL_TREE
&& ! TREE_STATIC (exp)
&& ! AGGREGATE_TYPE_P (TREE_TYPE (exp)))
{
enum memory_use_mode memory_usage;
memory_usage = get_memory_usage_from_modifier (modifier);
if (memory_usage != MEMORY_USE_DONT)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
XEXP (DECL_RTL (exp), 0), ptr_mode,
GEN_INT (int_size_in_bytes (type)),
TYPE_MODE (sizetype),
GEN_INT (memory_usage), QImode);
}
/* ... fall through ... */ /* ... fall through ... */
case FUNCTION_DECL: case FUNCTION_DECL:
...@@ -4889,7 +5080,8 @@ expand_expr (exp, target, tmode, modifier) ...@@ -4889,7 +5080,8 @@ expand_expr (exp, target, tmode, modifier)
mode); mode);
case CONST_DECL: case CONST_DECL:
return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0); return expand_expr (DECL_INITIAL (exp), target, VOIDmode,
EXPAND_MEMORY_USE_BAD);
case REAL_CST: case REAL_CST:
/* If optimized, generate immediate CONST_DOUBLE /* If optimized, generate immediate CONST_DOUBLE
...@@ -4982,7 +5174,8 @@ expand_expr (exp, target, tmode, modifier) ...@@ -4982,7 +5174,8 @@ expand_expr (exp, target, tmode, modifier)
} }
if (temp == const0_rtx) if (temp == const0_rtx)
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0); expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
EXPAND_MEMORY_USE_BAD);
else else
store_expr (TREE_OPERAND (exp, 0), temp, 0); store_expr (TREE_OPERAND (exp, 0), temp, 0);
} }
...@@ -5053,7 +5246,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5053,7 +5246,7 @@ expand_expr (exp, target, tmode, modifier)
In that case, we want to translate it using subsequent In that case, we want to translate it using subsequent
entries. */ entries. */
placeholder_list = TREE_CHAIN (placeholder_list); placeholder_list = TREE_CHAIN (placeholder_list);
temp = expand_expr (object, original_target, tmode, modifier); temp = expand_expr (object, original_target, tmode, ro_modifier);
placeholder_list = old_list; placeholder_list = old_list;
return temp; return temp;
} }
...@@ -5068,7 +5261,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5068,7 +5261,7 @@ expand_expr (exp, target, tmode, modifier)
placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE, placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
placeholder_list); placeholder_list);
target = expand_expr (TREE_OPERAND (exp, 0), original_target, target = expand_expr (TREE_OPERAND (exp, 0), original_target,
tmode, modifier); tmode, ro_modifier);
placeholder_list = TREE_CHAIN (placeholder_list); placeholder_list = TREE_CHAIN (placeholder_list);
return target; return target;
...@@ -5112,7 +5305,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5112,7 +5305,7 @@ expand_expr (exp, target, tmode, modifier)
vars = TREE_CHAIN (vars); vars = TREE_CHAIN (vars);
} }
temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier); temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, ro_modifier);
expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0); expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
...@@ -5138,7 +5331,8 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5138,7 +5331,8 @@ expand_expr (exp, target, tmode, modifier)
{ {
tree elt; tree elt;
for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt)) for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0); expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode,
EXPAND_MEMORY_USE_BAD);
return const0_rtx; return const0_rtx;
} }
...@@ -5207,6 +5401,19 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5207,6 +5401,19 @@ expand_expr (exp, target, tmode, modifier)
op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM); op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address (mode, op0); op0 = memory_address (mode, op0);
if (flag_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (exp)))
{
enum memory_use_mode memory_usage;
memory_usage = get_memory_usage_from_modifier (modifier);
if (memory_usage != MEMORY_USE_DONT)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
op0, ptr_mode,
GEN_INT (int_size_in_bytes (type)),
TYPE_MODE (sizetype),
GEN_INT (memory_usage), QImode);
}
temp = gen_rtx (MEM, mode, op0); temp = gen_rtx (MEM, mode, op0);
/* If address was computed by addition, /* If address was computed by addition,
mark this as an element of an aggregate. */ mark this as an element of an aggregate. */
...@@ -5286,7 +5493,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5286,7 +5493,7 @@ expand_expr (exp, target, tmode, modifier)
elem = TREE_CHAIN (elem); elem = TREE_CHAIN (elem);
if (elem) if (elem)
return expand_expr (fold (TREE_VALUE (elem)), target, return expand_expr (fold (TREE_VALUE (elem)), target,
tmode, modifier); tmode, ro_modifier);
} }
} }
...@@ -5309,7 +5516,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5309,7 +5516,7 @@ expand_expr (exp, target, tmode, modifier)
elem = TREE_CHAIN (elem); elem = TREE_CHAIN (elem);
if (elem) if (elem)
return expand_expr (fold (TREE_VALUE (elem)), target, return expand_expr (fold (TREE_VALUE (elem)), target,
tmode, modifier); tmode, ro_modifier);
} }
else if (TREE_CODE (init) == STRING_CST else if (TREE_CODE (init) == STRING_CST
&& TREE_INT_CST_HIGH (index) == 0 && TREE_INT_CST_HIGH (index) == 0
...@@ -5438,6 +5645,29 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5438,6 +5645,29 @@ expand_expr (exp, target, tmode, modifier)
MEM_VOLATILE_P (op0) = 1; MEM_VOLATILE_P (op0) = 1;
} }
/* Check the access. */
if (flag_check_memory_usage && GET_CODE (op0) == MEM)
{
enum memory_use_mode memory_usage;
memory_usage = get_memory_usage_from_modifier (modifier);
if (memory_usage != MEMORY_USE_DONT)
{
rtx to;
int size;
to = plus_constant (XEXP (op0, 0), (bitpos / BITS_PER_UNIT));
size = (bitpos % BITS_PER_UNIT) + bitsize + BITS_PER_UNIT - 1;
/* Check the access right of the pointer. */
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
to, ptr_mode,
GEN_INT (size / BITS_PER_UNIT),
TYPE_MODE (sizetype),
GEN_INT (memory_usage), QImode);
}
}
/* In cases where an aligned union has an unaligned object /* In cases where an aligned union has an unaligned object
as a field, we might be extracting a BLKmode value from as a field, we might be extracting a BLKmode value from
an integer-mode (e.g., SImode) object. Handle this case an integer-mode (e.g., SImode) object. Handle this case
...@@ -5671,7 +5901,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5671,7 +5901,7 @@ expand_expr (exp, target, tmode, modifier)
if (RTL_EXPR_RTL (exp) == 0) if (RTL_EXPR_RTL (exp) == 0)
{ {
RTL_EXPR_RTL (exp) RTL_EXPR_RTL (exp)
= expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); = expand_expr (TREE_OPERAND (exp, 0), target, tmode, ro_modifier);
expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 2)); expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 2));
/* That's it for this cleanup. */ /* That's it for this cleanup. */
...@@ -5688,7 +5918,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5688,7 +5918,7 @@ expand_expr (exp, target, tmode, modifier)
target_temp_slot_level = temp_slot_level; target_temp_slot_level = temp_slot_level;
op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, ro_modifier);
/* If we're going to use this value, load it up now. */ /* If we're going to use this value, load it up now. */
if (! ignore) if (! ignore)
op0 = force_not_mem (op0); op0 = force_not_mem (op0);
...@@ -5748,7 +5978,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5748,7 +5978,7 @@ expand_expr (exp, target, tmode, modifier)
if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
{ {
op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode,
modifier); ro_modifier);
/* If the signedness of the conversion differs and OP0 is /* If the signedness of the conversion differs and OP0 is
a promoted SUBREG, clear that indication since we now a promoted SUBREG, clear that indication since we now
...@@ -5870,8 +6100,8 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5870,8 +6100,8 @@ expand_expr (exp, target, tmode, modifier)
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1))) if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
subtarget = 0; subtarget = 0;
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, ro_modifier);
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier); op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, ro_modifier);
both_summands: both_summands:
/* Make sure any term that's a sum with a constant comes last. */ /* Make sure any term that's a sum with a constant comes last. */
...@@ -5931,9 +6161,9 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5931,9 +6161,9 @@ expand_expr (exp, target, tmode, modifier)
&& really_constant_p (TREE_OPERAND (exp, 1))) && really_constant_p (TREE_OPERAND (exp, 1)))
{ {
rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX,
VOIDmode, modifier); VOIDmode, ro_modifier);
rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
VOIDmode, modifier); VOIDmode, ro_modifier);
/* If the last operand is a CONST_INT, use plus_constant of /* If the last operand is a CONST_INT, use plus_constant of
the negated constant. Else make the MINUS. */ the negated constant. Else make the MINUS. */
...@@ -5961,7 +6191,7 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5961,7 +6191,7 @@ expand_expr (exp, target, tmode, modifier)
return expand_expr (convert (type, return expand_expr (convert (type,
build (PLUS_EXPR, newtype, build (PLUS_EXPR, newtype,
newop0, newneg)), newop0, newneg)),
target, tmode, modifier); target, tmode, ro_modifier);
} }
else else
{ {
...@@ -5991,7 +6221,8 @@ expand_expr (exp, target, tmode, modifier) ...@@ -5991,7 +6221,8 @@ expand_expr (exp, target, tmode, modifier)
&& TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
{ {
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
EXPAND_SUM);
/* Apply distributive law if OP0 is x+c. */ /* Apply distributive law if OP0 is x+c. */
if (GET_CODE (op0) == PLUS if (GET_CODE (op0) == PLUS
...@@ -6415,11 +6646,11 @@ expand_expr (exp, target, tmode, modifier) ...@@ -6415,11 +6646,11 @@ expand_expr (exp, target, tmode, modifier)
if (ignore) if (ignore)
{ {
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
modifier); ro_modifier);
return const0_rtx; return const0_rtx;
} }
op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier); op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, ro_modifier);
if (GET_MODE (op0) == mode) if (GET_MODE (op0) == mode)
return op0; return op0;
...@@ -8278,7 +8509,7 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -8278,7 +8509,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
TREE_STATIC (result) = 1; TREE_STATIC (result) = 1;
result = build (INDIRECT_REF, build_pointer_type (type), result); result = build (INDIRECT_REF, build_pointer_type (type), result);
TREE_CONSTANT (result) = 1; TREE_CONSTANT (result) = 1;
return expand_expr (result, NULL_RTX, VOIDmode, 0); return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
#endif #endif
} }
...@@ -8422,6 +8653,16 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -8422,6 +8653,16 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return tem; return tem;
} }
/* Returns the address of the area where the structure is returned.
0 otherwise. */
case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
if (arglist != 0
|| ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
|| GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
return const0_rtx;
else
return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
case BUILT_IN_ALLOCA: case BUILT_IN_ALLOCA:
if (arglist == 0 if (arglist == 0
/* Arg could be non-integer if user redeclared this fcn wrong. */ /* Arg could be non-integer if user redeclared this fcn wrong. */
...@@ -8477,7 +8718,7 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -8477,7 +8718,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
/* If the length is known, just return it. */ /* If the length is known, just return it. */
if (len != 0) if (len != 0)
return expand_expr (len, target, mode, 0); return expand_expr (len, target, mode, EXPAND_MEMORY_USE_BAD);
/* If SRC is not a pointer type, don't do this operation inline. */ /* If SRC is not a pointer type, don't do this operation inline. */
if (align == 0) if (align == 0)
...@@ -9427,7 +9668,7 @@ expand_increment (exp, post, ignore) ...@@ -9427,7 +9668,7 @@ expand_increment (exp, post, ignore)
and insns were generated in computing it. */ and insns were generated in computing it. */
temp = get_last_insn (); temp = get_last_insn ();
op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0); op0 = expand_expr (incremented, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_RW);
/* If OP0 is a SUBREG made for a promoted variable, we cannot increment /* If OP0 is a SUBREG made for a promoted variable, we cannot increment
in place but instead must do sign- or zero-extension during assignment, in place but instead must do sign- or zero-extension during assignment,
...@@ -9458,7 +9699,8 @@ expand_increment (exp, post, ignore) ...@@ -9458,7 +9699,8 @@ expand_increment (exp, post, ignore)
op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
&& temp != get_last_insn ()); && temp != get_last_insn ());
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
EXPAND_MEMORY_USE_BAD);
/* Decide whether incrementing or decrementing. */ /* Decide whether incrementing or decrementing. */
if (TREE_CODE (exp) == POSTDECREMENT_EXPR if (TREE_CODE (exp) == POSTDECREMENT_EXPR
...@@ -9574,7 +9816,8 @@ expand_increment (exp, post, ignore) ...@@ -9574,7 +9816,8 @@ expand_increment (exp, post, ignore)
temp = copy_rtx (value = op0); temp = copy_rtx (value = op0);
/* Increment however we can. */ /* Increment however we can. */
op1 = expand_binop (mode, this_optab, value, op1, op0, op1 = expand_binop (mode, this_optab, value, op1,
flag_check_memory_usage ? NULL_RTX : op0,
TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN); TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
/* Make sure the value is stored into OP0. */ /* Make sure the value is stored into OP0. */
if (op1 != op0) if (op1 != op0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment