aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2002-04-22 19:26:19 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2002-04-22 19:26:19 +0000
commit8ed8f73189d98d9960c23061be9b0cdefa7c8f0d (patch)
tree898af6988a88f160710755e9b4a121324c754dcc /gcc/function.c
parentb2e4f4fda73c761ee3d7f817378241d04f11a936 (diff)
downloadgcc-8ed8f73189d98d9960c23061be9b0cdefa7c8f0d.zip
gcc-8ed8f73189d98d9960c23061be9b0cdefa7c8f0d.tar.gz
gcc-8ed8f73189d98d9960c23061be9b0cdefa7c8f0d.tar.bz2
re PR fortran/6138 (Incorrect access of integer*1 variables on PA)
PR f/6138. * function.c (fixup_memory_subreg): Add promoted_mode parameter. (walk_fixup_memory_subreg): Likewise. (fixup_var_refs_insn): Adjust accordingly. (fixup_var_refs_1): Likewise. From-SVN: r52631
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c84
1 files changed, 54 insertions, 30 deletions
diff --git a/gcc/function.c b/gcc/function.c
index e22273d..5904919 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -246,8 +246,9 @@ static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode,
int, int, rtx));
static void fixup_var_refs_1 PARAMS ((rtx, enum machine_mode, rtx *, rtx,
struct fixup_replacement **, rtx));
-static rtx fixup_memory_subreg PARAMS ((rtx, rtx, int));
-static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, int));
+static rtx fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int));
+static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode,
+ int));
static rtx fixup_stack_1 PARAMS ((rtx, rtx));
static void optimize_bit_field PARAMS ((rtx, rtx, rtx *));
static void instantiate_decls PARAMS ((tree, int));
@@ -1859,7 +1860,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
/* OLD might be a (subreg (mem)). */
if (GET_CODE (replacements->old) == SUBREG)
replacements->old
- = fixup_memory_subreg (replacements->old, insn, 0);
+ = fixup_memory_subreg (replacements->old, insn,
+ promoted_mode, 0);
else
replacements->old
= fixup_stack_1 (replacements->old, insn);
@@ -1899,7 +1901,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
{
if (GET_CODE (note) != INSN_LIST)
XEXP (note, 0)
- = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
+ = walk_fixup_memory_subreg (XEXP (note, 0), insn,
+ promoted_mode, 1);
note = XEXP (note, 1);
}
}
@@ -2070,7 +2073,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
return;
}
else
- tem = fixup_memory_subreg (tem, insn, 0);
+ tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
}
else
tem = fixup_stack_1 (tem, insn);
@@ -2185,7 +2188,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
return;
}
- replacement->new = *loc = fixup_memory_subreg (x, insn, 0);
+ replacement->new = *loc = fixup_memory_subreg (x, insn,
+ promoted_mode, 0);
INSN_CODE (insn) = -1;
if (! flag_force_mem && recog_memoized (insn) >= 0)
@@ -2276,7 +2280,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
This was legitimate when the MEM was a REG. */
if (GET_CODE (tem) == SUBREG
&& SUBREG_REG (tem) == var)
- tem = fixup_memory_subreg (tem, insn, 0);
+ tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
else
tem = fixup_stack_1 (tem, insn);
@@ -2378,7 +2382,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
SET_SRC (x) = replacement->new;
else if (GET_CODE (SET_SRC (x)) == SUBREG)
SET_SRC (x) = replacement->new
- = fixup_memory_subreg (SET_SRC (x), insn, 0);
+ = fixup_memory_subreg (SET_SRC (x), insn, promoted_mode,
+ 0);
else
SET_SRC (x) = replacement->new
= fixup_stack_1 (SET_SRC (x), insn);
@@ -2431,7 +2436,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
rtx pat, last;
if (GET_CODE (SET_DEST (x)) == SUBREG)
- SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0);
+ SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn,
+ promoted_mode, 0);
else
SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
@@ -2476,6 +2482,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
{
rtx temp;
rtx fixeddest = SET_DEST (x);
+ enum machine_mode temp_mode;
/* STRICT_LOW_PART can be discarded, around a MEM. */
if (GET_CODE (fixeddest) == STRICT_LOW_PART)
@@ -2483,13 +2490,17 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
/* Convert (SUBREG (MEM)) to a MEM in a changed mode. */
if (GET_CODE (fixeddest) == SUBREG)
{
- fixeddest = fixup_memory_subreg (fixeddest, insn, 0);
- promoted_mode = GET_MODE (fixeddest);
+ fixeddest = fixup_memory_subreg (fixeddest, insn,
+ promoted_mode, 0);
+ temp_mode = GET_MODE (fixeddest);
}
else
- fixeddest = fixup_stack_1 (fixeddest, insn);
+ {
+ fixeddest = fixup_stack_1 (fixeddest, insn);
+ temp_mode = promoted_mode;
+ }
- temp = gen_reg_rtx (promoted_mode);
+ temp = gen_reg_rtx (temp_mode);
emit_insn_after (gen_move_insn (fixeddest,
gen_lowpart (GET_MODE (fixeddest),
@@ -2522,36 +2533,47 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
}
}
-/* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),
- return an rtx (MEM:m1 newaddr) which is equivalent.
- If any insns must be emitted to compute NEWADDR, put them before INSN.
+/* Previously, X had the form (SUBREG:m1 (REG:PROMOTED_MODE ...)).
+ The REG was placed on the stack, so X now has the form (SUBREG:m1
+ (MEM:m2 ...)).
+
+ Return an rtx (MEM:m1 newaddr) which is equivalent. If any insns
+ must be emitted to compute NEWADDR, put them before INSN.
UNCRITICAL nonzero means accept paradoxical subregs.
This is used for subregs found inside REG_NOTES. */
static rtx
-fixup_memory_subreg (x, insn, uncritical)
+fixup_memory_subreg (x, insn, promoted_mode, uncritical)
rtx x;
rtx insn;
+ enum machine_mode promoted_mode;
int uncritical;
{
- int offset = SUBREG_BYTE (x);
- rtx addr = XEXP (SUBREG_REG (x), 0);
+ int offset;
+ rtx mem = SUBREG_REG (x);
+ rtx addr = XEXP (mem, 0);
enum machine_mode mode = GET_MODE (x);
rtx result;
/* Paradoxical SUBREGs are usually invalid during RTL generation. */
- if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- && ! uncritical)
+ if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical)
abort ();
+ offset = SUBREG_BYTE (x);
+ if (BYTES_BIG_ENDIAN)
+ /* If the PROMOTED_MODE is wider than the mode of the MEM, adjust
+ the offset so that it points to the right location within the
+ MEM. */
+ offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem)));
+
if (!flag_force_addr
&& memory_address_p (mode, plus_constant (addr, offset)))
/* Shortcut if no insns need be emitted. */
- return adjust_address (SUBREG_REG (x), mode, offset);
+ return adjust_address (mem, mode, offset);
start_sequence ();
- result = adjust_address (SUBREG_REG (x), mode, offset);
+ result = adjust_address (mem, mode, offset);
emit_insn_before (gen_sequence (), insn);
end_sequence ();
return result;
@@ -2562,14 +2584,14 @@ fixup_memory_subreg (x, insn, uncritical)
If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
Otherwise return X, with its contents possibly altered.
- If any insns must be emitted to compute NEWADDR, put them before INSN.
-
- UNCRITICAL is as in fixup_memory_subreg. */
+ INSN, PROMOTED_MODE and UNCRITICAL are as for
+ fixup_memory_subreg. */
static rtx
-walk_fixup_memory_subreg (x, insn, uncritical)
+walk_fixup_memory_subreg (x, insn, promoted_mode, uncritical)
rtx x;
rtx insn;
+ enum machine_mode promoted_mode;
int uncritical;
{
enum rtx_code code;
@@ -2582,7 +2604,7 @@ walk_fixup_memory_subreg (x, insn, uncritical)
code = GET_CODE (x);
if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
- return fixup_memory_subreg (x, insn, uncritical);
+ return fixup_memory_subreg (x, insn, promoted_mode, uncritical);
/* Nothing special about this RTX; fix its operands. */
@@ -2590,13 +2612,15 @@ walk_fixup_memory_subreg (x, insn, uncritical)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, uncritical);
+ XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn,
+ promoted_mode, uncritical);
else if (fmt[i] == 'E')
{
int j;
for (j = 0; j < XVECLEN (x, i); j++)
XVECEXP (x, i, j)
- = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, uncritical);
+ = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn,
+ promoted_mode, uncritical);
}
}
return x;